Compare commits
4 Commits
d688f8a2b5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
e132275d33
|
|||
|
bf432161fb
|
|||
|
a93fa4a8be
|
|||
|
8d5658ee7a
|
@@ -7,7 +7,7 @@ RUN apt update && apt install --yes --no-install-recommends wget git apt-transpo
|
|||||||
|
|
||||||
ENV GIT_REPOSITORY=https://github.com/tornadocontrib/tornado-scripts.git
|
ENV GIT_REPOSITORY=https://github.com/tornadocontrib/tornado-scripts.git
|
||||||
# From main branch, double check with git.tornado.ws and codeberg.org
|
# From main branch, double check with git.tornado.ws and codeberg.org
|
||||||
ENV GIT_COMMIT_HASH=0aa9f0038354412e01b171df7dcff96b1c55976c
|
ENV GIT_COMMIT_HASH=8d5658ee7aedbaa2413868c4c9e0fb453a92ae64
|
||||||
|
|
||||||
# clone the repository
|
# clone the repository
|
||||||
RUN mkdir /app/
|
RUN mkdir /app/
|
||||||
|
|||||||
44
dist/events/base.d.ts
vendored
44
dist/events/base.d.ts
vendored
@@ -1,9 +1,9 @@
|
|||||||
import { BaseContract, Provider, EventLog } from 'ethers';
|
import { BaseContract, Provider, EventLog } from 'ethers';
|
||||||
import { Tornado, TornadoRouter, TornadoProxyLight, Governance, RelayerRegistry, Echoer, Aggregator } from 'tornado-contracts';
|
import { Tornado, TornadoRouter, TornadoProxyLight, Governance, RelayerRegistry, Echoer, TovarishAggregator } from 'tornado-contracts';
|
||||||
import type { MerkleTree } from 'fixed-merkle-tree';
|
import type { MerkleTree } from 'fixed-merkle-tree';
|
||||||
import { BatchEventsService, BatchBlockService, BatchTransactionService, BatchEventOnProgress, BatchBlockOnProgress } from '../batch';
|
import { BatchEventsService, BatchBlockService, BatchTransactionService, BatchEventOnProgress, BatchBlockOnProgress } from '../batch';
|
||||||
import { fetchDataOptions } from '../providers';
|
import { fetchDataOptions } from '../providers';
|
||||||
import { type NetIdType, type SubdomainMap } from '../networkConfig';
|
import { TornadoConfig, type NetIdType, type SubdomainMap } from '../networkConfig';
|
||||||
import { RelayerParams } from '../relayerClient';
|
import { RelayerParams } from '../relayerClient';
|
||||||
import type { TovarishClient } from '../tovarishClient';
|
import type { TovarishClient } from '../tovarishClient';
|
||||||
import type { ERC20, ReverseRecords } from '../typechain';
|
import type { ERC20, ReverseRecords } from '../typechain';
|
||||||
@@ -158,12 +158,12 @@ export interface GovernanceVotes extends GovernanceVotedEvents {
|
|||||||
}
|
}
|
||||||
export interface BaseGovernanceServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
export interface BaseGovernanceServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||||
Governance: Governance;
|
Governance: Governance;
|
||||||
Aggregator: Aggregator;
|
Aggregator: TovarishAggregator;
|
||||||
ReverseRecords: ReverseRecords;
|
ReverseRecords: ReverseRecords;
|
||||||
}
|
}
|
||||||
export declare class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents> {
|
export declare class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents> {
|
||||||
Governance: Governance;
|
Governance: Governance;
|
||||||
Aggregator: Aggregator;
|
Aggregator: TovarishAggregator;
|
||||||
ReverseRecords: ReverseRecords;
|
ReverseRecords: ReverseRecords;
|
||||||
batchTransactionService: BatchTransactionService;
|
batchTransactionService: BatchTransactionService;
|
||||||
constructor(serviceConstructor: BaseGovernanceServiceConstructor);
|
constructor(serviceConstructor: BaseGovernanceServiceConstructor);
|
||||||
@@ -181,7 +181,6 @@ export declare class BaseGovernanceService extends BaseEventsService<AllGovernan
|
|||||||
balance: bigint;
|
balance: bigint;
|
||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
export declare function getTovarishNetworks(registryService: BaseRegistryService, relayers: CachedRelayerInfo[]): Promise<void>;
|
|
||||||
/**
|
/**
|
||||||
* Essential params:
|
* Essential params:
|
||||||
* ensName, relayerAddress, hostnames
|
* ensName, relayerAddress, hostnames
|
||||||
@@ -189,49 +188,26 @@ export declare function getTovarishNetworks(registryService: BaseRegistryService
|
|||||||
*/
|
*/
|
||||||
export interface CachedRelayerInfo extends RelayerParams {
|
export interface CachedRelayerInfo extends RelayerParams {
|
||||||
isRegistered?: boolean;
|
isRegistered?: boolean;
|
||||||
registeredAddress?: string;
|
isPrior?: boolean;
|
||||||
stakeBalance?: string;
|
stakeBalance?: string;
|
||||||
hostnames: SubdomainMap;
|
hostnames: SubdomainMap;
|
||||||
tovarishHost?: string;
|
tovarishHost?: string;
|
||||||
tovarishNetworks?: number[];
|
tovarishNetworks?: number[];
|
||||||
}
|
}
|
||||||
export interface CachedRelayers {
|
|
||||||
lastBlock: number;
|
|
||||||
timestamp: number;
|
|
||||||
relayers: CachedRelayerInfo[];
|
|
||||||
fromCache?: boolean;
|
|
||||||
}
|
|
||||||
export interface BaseRegistryServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
export interface BaseRegistryServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||||
|
tornadoConfig: TornadoConfig;
|
||||||
RelayerRegistry: RelayerRegistry;
|
RelayerRegistry: RelayerRegistry;
|
||||||
Aggregator: Aggregator;
|
Aggregator: TovarishAggregator;
|
||||||
relayerEnsSubdomains: SubdomainMap;
|
|
||||||
}
|
}
|
||||||
export declare class BaseRegistryService extends BaseEventsService<AllRelayerRegistryEvents> {
|
export declare class BaseRegistryService extends BaseEventsService<AllRelayerRegistryEvents> {
|
||||||
Aggregator: Aggregator;
|
tornadoConfig: TornadoConfig;
|
||||||
relayerEnsSubdomains: SubdomainMap;
|
Aggregator: TovarishAggregator;
|
||||||
updateInterval: number;
|
updateInterval: number;
|
||||||
constructor(serviceConstructor: BaseRegistryServiceConstructor);
|
constructor(serviceConstructor: BaseRegistryServiceConstructor);
|
||||||
getInstanceName(): string;
|
getInstanceName(): string;
|
||||||
getTovarishType(): string;
|
getTovarishType(): string;
|
||||||
formatEvents(events: EventLog[]): Promise<AllRelayerRegistryEvents[]>;
|
formatEvents(events: EventLog[]): Promise<AllRelayerRegistryEvents[]>;
|
||||||
/**
|
getLatestRelayers(knownRelayers?: string[]): Promise<CachedRelayerInfo[]>;
|
||||||
* Get saved or cached relayers
|
|
||||||
*/
|
|
||||||
getRelayersFromDB(): Promise<CachedRelayers>;
|
|
||||||
/**
|
|
||||||
* Relayers from remote cache (Either from local cache, CDN, or from IPFS)
|
|
||||||
*/
|
|
||||||
getRelayersFromCache(): Promise<CachedRelayers>;
|
|
||||||
getSavedRelayers(): Promise<CachedRelayers>;
|
|
||||||
getLatestRelayers(): Promise<CachedRelayers>;
|
|
||||||
/**
|
|
||||||
* Handle saving relayers
|
|
||||||
*/
|
|
||||||
saveRelayers({ lastBlock, timestamp, relayers }: CachedRelayers): Promise<void>;
|
|
||||||
/**
|
|
||||||
* Get cached or latest relayer and save to local
|
|
||||||
*/
|
|
||||||
updateRelayers(): Promise<CachedRelayers>;
|
|
||||||
}
|
}
|
||||||
export interface BaseRevenueServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
export interface BaseRevenueServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||||
RelayerRegistry: RelayerRegistry;
|
RelayerRegistry: RelayerRegistry;
|
||||||
|
|||||||
6
dist/events/db.d.ts
vendored
6
dist/events/db.d.ts
vendored
@@ -1,5 +1,5 @@
|
|||||||
import { IndexedDB } from '../idb';
|
import { IndexedDB } from '../idb';
|
||||||
import { BaseTornadoService, BaseTornadoServiceConstructor, BaseEchoService, BaseEchoServiceConstructor, BaseEncryptedNotesService, BaseEncryptedNotesServiceConstructor, BaseGovernanceService, BaseGovernanceServiceConstructor, BaseRegistryService, BaseRegistryServiceConstructor, BaseRevenueService, BaseRevenueServiceConstructor, CachedRelayers, BaseMultiTornadoService, BaseMultiTornadoServiceConstructor } from './base';
|
import { BaseTornadoService, BaseTornadoServiceConstructor, BaseEchoService, BaseEchoServiceConstructor, BaseEncryptedNotesService, BaseEncryptedNotesServiceConstructor, BaseGovernanceService, BaseGovernanceServiceConstructor, BaseRegistryService, BaseRegistryServiceConstructor, BaseRevenueService, BaseRevenueServiceConstructor, BaseMultiTornadoService, BaseMultiTornadoServiceConstructor } from './base';
|
||||||
import { BaseEvents, MinimalEvents, DepositsEvents, WithdrawalsEvents, CachedEvents, EchoEvents, EncryptedNotesEvents, AllGovernanceEvents, AllRelayerRegistryEvents, StakeBurnedEvents, MultiDepositsEvents, MultiWithdrawalsEvents } from './types';
|
import { BaseEvents, MinimalEvents, DepositsEvents, WithdrawalsEvents, CachedEvents, EchoEvents, EncryptedNotesEvents, AllGovernanceEvents, AllRelayerRegistryEvents, StakeBurnedEvents, MultiDepositsEvents, MultiWithdrawalsEvents } from './types';
|
||||||
export declare function saveDBEvents<T extends MinimalEvents>({ idb, instanceName, newEvents, lastBlock, }: {
|
export declare function saveDBEvents<T extends MinimalEvents>({ idb, instanceName, newEvents, lastBlock, }: {
|
||||||
idb: IndexedDB;
|
idb: IndexedDB;
|
||||||
@@ -100,16 +100,12 @@ export declare class DBRegistryService extends BaseRegistryService {
|
|||||||
staticUrl: string;
|
staticUrl: string;
|
||||||
idb: IndexedDB;
|
idb: IndexedDB;
|
||||||
zipDigest?: string;
|
zipDigest?: string;
|
||||||
relayerJsonDigest?: string;
|
|
||||||
constructor(params: DBRegistryServiceConstructor);
|
constructor(params: DBRegistryServiceConstructor);
|
||||||
getEventsFromDB(): Promise<BaseEvents<AllRelayerRegistryEvents>>;
|
getEventsFromDB(): Promise<BaseEvents<AllRelayerRegistryEvents>>;
|
||||||
getEventsFromCache(): Promise<CachedEvents<AllRelayerRegistryEvents>>;
|
getEventsFromCache(): Promise<CachedEvents<AllRelayerRegistryEvents>>;
|
||||||
saveEvents({ newEvents, lastBlock, }: BaseEvents<AllRelayerRegistryEvents> & {
|
saveEvents({ newEvents, lastBlock, }: BaseEvents<AllRelayerRegistryEvents> & {
|
||||||
newEvents: AllRelayerRegistryEvents[];
|
newEvents: AllRelayerRegistryEvents[];
|
||||||
}): Promise<void>;
|
}): Promise<void>;
|
||||||
getRelayersFromDB(): Promise<CachedRelayers>;
|
|
||||||
getRelayersFromCache(): Promise<CachedRelayers>;
|
|
||||||
saveRelayers(cachedRelayers: CachedRelayers): Promise<void>;
|
|
||||||
}
|
}
|
||||||
export interface DBRevenueServiceConstructor extends BaseRevenueServiceConstructor {
|
export interface DBRevenueServiceConstructor extends BaseRevenueServiceConstructor {
|
||||||
staticUrl: string;
|
staticUrl: string;
|
||||||
|
|||||||
18
dist/hashes.json
vendored
18
dist/hashes.json
vendored
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"dist/index.js": "sha384-iQ5shLTi2Nyi35ciUUQRXg2JSgjBguTRXafhYVZuuAyJug9BAXZIWYEwupPOUcCo",
|
"dist/index.js": "sha384-ILYwPMkfXtfslWBdxqmKYYq4yDnJf3tKKgW5Am0P4NnpLW9z5m/wlLBuITa51727",
|
||||||
"dist/index.mjs": "sha384-Lx8Qc+R6ak1AaPmSKJ06+EYyFuVF8gI7E+IvBFItO+3Yoc+JmsunEmytkd7mhSQt",
|
"dist/index.mjs": "sha384-bgbAMKtG/iKiZKdITr1E+i14xCVp17/Yj8/O5bCE8BMnqlwTY/XvmLe8+EWmvB/s",
|
||||||
"dist/merkleTreeWorker.js": "sha384-gib4Z6KDvYxUpNTSc4YA2dX5FxaQe2FiorGkBJJDfm86tXdT+57T2Gt+ti6YXTeX",
|
"dist/merkleTreeWorker.js": "sha384-CJID2MqR6z42NYw9ZXhHAZ05+7YrQg0YJDwJLB/qhOhIJYt3am2wVZdR/W7njnuZ",
|
||||||
"dist/merkleTreeWorker.umd.js": "sha384-yHNYOc2TzXlkKS8/5dzjggHQmOJw2mRIB8DqagRTQxUP/p6uPXyp07LqXeOHNfv7",
|
"dist/merkleTreeWorker.umd.js": "sha384-6uVyasRLcNVbdsuJSbgzxfSQ/0yRURWhP6oULhW6jffTNJzpMWay6/ie9pQVUj78",
|
||||||
"dist/merkleTreeWorker.umd.min.js": "sha384-Hpupvso1ruJIgbYwq+dySfLb75sgwxUexPYSCJu+/i7U3XqR6JiBhWOEnAdxR/An",
|
"dist/merkleTreeWorker.umd.min.js": "sha384-LUERJw4t5HapI287NVtz3VtnqjXXrC7yBdxMQHpkTX8ZGOjp5fyEqYb1KENzNY9R",
|
||||||
"dist/tornado.umd.js": "sha384-ovBwiI34m1uBSV4UlKomzexgVturp0Uq7O207DMS96GwpOeOjdS1RMkh7rqmtMed",
|
"dist/tornado.umd.js": "sha384-IXBljLi80UVwQj0arsdDbOLEQlHfXFAKbAencbqDgqyUaRs7mjsYJDFe+wPgB/ie",
|
||||||
"dist/tornado.umd.min.js": "sha384-z9UM5/+q0Z70nAb+8JebUO/78o9C/W1AZgOWOYsDAyL9sH8ANR9U9tfB467+QHCF",
|
"dist/tornado.umd.min.js": "sha384-FwrFV3WOdr2uBRdFyPIKJU+gCybthzvw6+D9GDTRAYflL+Kh8C3hUyk7qsJJGGvq",
|
||||||
"dist/tornadoContracts.umd.js": "sha384-Gmawcz/XTH7WFUFnMJKPUCy2zrjDOhf/DtSv9xfHBulPyCEJwI70Hw+n7E1Y60EU",
|
"dist/tornadoContracts.umd.js": "sha384-wOj+yVI78CBtmwvEn3l/ko3CEbtaqHXbx69pKraBOLOkz98HlJSSTcKs/spf0Ods",
|
||||||
"dist/tornadoContracts.umd.min.js": "sha384-Sclkp3xkhjmDekfQaQFkgUctmauYUF7ieeyyFhFBnwAzyp2eFBS5qzxvOIBhlJza"
|
"dist/tornadoContracts.umd.min.js": "sha384-LMcw1ogbZefmFD6HUNEOnhIYizZEWtRW2FqUIglSxk5i1qoDq1+iZolSaGheQfx9"
|
||||||
}
|
}
|
||||||
4
dist/idb.d.ts
vendored
4
dist/idb.d.ts
vendored
@@ -1,6 +1,6 @@
|
|||||||
import type * as idb from 'idb';
|
import type * as idb from 'idb';
|
||||||
import type { OpenDBCallbacks, IDBPDatabase } from 'idb';
|
import type { OpenDBCallbacks, IDBPDatabase } from 'idb';
|
||||||
import { NetIdType } from './networkConfig';
|
import type { NetIdType, TornadoConfig } from './networkConfig';
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
idb: typeof idb;
|
idb: typeof idb;
|
||||||
@@ -87,4 +87,4 @@ export declare class IndexedDB {
|
|||||||
/**
|
/**
|
||||||
* Should check if DB is initialized well
|
* Should check if DB is initialized well
|
||||||
*/
|
*/
|
||||||
export declare function getIndexedDB(netId?: NetIdType): Promise<IndexedDB>;
|
export declare function getIndexedDB(netId?: NetIdType, tornadoConfig?: TornadoConfig): Promise<IndexedDB>;
|
||||||
|
|||||||
1843
dist/index.js
vendored
1843
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
1827
dist/index.mjs
vendored
1827
dist/index.mjs
vendored
File diff suppressed because it is too large
Load Diff
11
dist/ip.d.ts
vendored
11
dist/ip.d.ts
vendored
@@ -7,3 +7,14 @@ export interface IPResult {
|
|||||||
tor?: boolean;
|
tor?: boolean;
|
||||||
}
|
}
|
||||||
export declare function fetchIp(ipEcho: string, fetchOptions?: fetchDataOptions): Promise<IPResult>;
|
export declare function fetchIp(ipEcho: string, fetchOptions?: fetchDataOptions): Promise<IPResult>;
|
||||||
|
export interface IPResultFuck {
|
||||||
|
YourFuckingIPAddress: string;
|
||||||
|
YourFuckingLocation: string;
|
||||||
|
YourFuckingHostname: string;
|
||||||
|
YourFuckingISP: string;
|
||||||
|
YourFuckingTorExit: boolean;
|
||||||
|
YourFuckingCity?: string;
|
||||||
|
YourFuckingCountry: string;
|
||||||
|
YourFuckingCountryCode: string;
|
||||||
|
}
|
||||||
|
export declare function fetchFuckingIp(ipFuck?: string, fetchOptions?: fetchDataOptions): Promise<IPResultFuck>;
|
||||||
|
|||||||
6
dist/merkleTreeWorker.js
vendored
6
dist/merkleTreeWorker.js
vendored
@@ -214,7 +214,7 @@ var hasRequiredFixedMerkleTree;
|
|||||||
function requireFixedMerkleTree () {
|
function requireFixedMerkleTree () {
|
||||||
if (hasRequiredFixedMerkleTree) return FixedMerkleTree;
|
if (hasRequiredFixedMerkleTree) return FixedMerkleTree;
|
||||||
hasRequiredFixedMerkleTree = 1;
|
hasRequiredFixedMerkleTree = 1;
|
||||||
var __importDefault = (FixedMerkleTree.__importDefault) || function (mod) {
|
var __importDefault = (FixedMerkleTree && FixedMerkleTree.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(FixedMerkleTree, "__esModule", { value: true });
|
Object.defineProperty(FixedMerkleTree, "__esModule", { value: true });
|
||||||
@@ -337,7 +337,7 @@ var hasRequiredPartialMerkleTree;
|
|||||||
function requirePartialMerkleTree () {
|
function requirePartialMerkleTree () {
|
||||||
if (hasRequiredPartialMerkleTree) return PartialMerkleTree;
|
if (hasRequiredPartialMerkleTree) return PartialMerkleTree;
|
||||||
hasRequiredPartialMerkleTree = 1;
|
hasRequiredPartialMerkleTree = 1;
|
||||||
var __importDefault = (PartialMerkleTree.__importDefault) || function (mod) {
|
var __importDefault = (PartialMerkleTree && PartialMerkleTree.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(PartialMerkleTree, "__esModule", { value: true });
|
Object.defineProperty(PartialMerkleTree, "__esModule", { value: true });
|
||||||
@@ -504,7 +504,7 @@ function requireLib () {
|
|||||||
if (hasRequiredLib) return lib;
|
if (hasRequiredLib) return lib;
|
||||||
hasRequiredLib = 1;
|
hasRequiredLib = 1;
|
||||||
(function (exports) {
|
(function (exports) {
|
||||||
var __importDefault = (lib.__importDefault) || function (mod) {
|
var __importDefault = (lib && lib.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
|||||||
122826
dist/merkleTreeWorker.umd.js
vendored
122826
dist/merkleTreeWorker.umd.js
vendored
File diff suppressed because one or more lines are too long
2
dist/merkleTreeWorker.umd.min.js
vendored
2
dist/merkleTreeWorker.umd.min.js
vendored
File diff suppressed because one or more lines are too long
152
dist/networkConfig.d.ts
vendored
152
dist/networkConfig.d.ts
vendored
@@ -1,4 +1,12 @@
|
|||||||
import type { DepositType } from './deposits';
|
import type { DepositType } from './deposits';
|
||||||
|
export declare const MERKLE_TREE_HEIGHT = 20;
|
||||||
|
export declare const EMPTY_ELEMENT = "21663839004416932945382355908790599225266501822907911457504978515578255421292";
|
||||||
|
export declare const MULTICALL_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
||||||
|
export declare const ONEINCH_ORACLE_ADDRESS = "0x00000000000D6FFc74A8feb35aF5827bf57f6786";
|
||||||
|
export declare const TORNADO_PROXY_LIGHT_ADDRESS = "0x0D5550d52428E7e3175bfc9550207e4ad3859b17";
|
||||||
|
export declare const ECHOER_ADDRESS = "0xa75BF2815618872f155b7C4B0C81bF990f5245E4";
|
||||||
|
export declare const TOVARISH_REGISTRY_ADDRESS = "0xc9D5C487c10bC755d34029b1135FA1c190d80f9b";
|
||||||
|
export declare const TOVARISH_AGGREGATOR_ADDRESS = "0x7A51f64A277d3597475Ea28283d0423764613231";
|
||||||
/**
|
/**
|
||||||
* Type of default supported networks
|
* Type of default supported networks
|
||||||
*/
|
*/
|
||||||
@@ -15,36 +23,76 @@ export declare enum NetId {
|
|||||||
SEPOLIA = 11155111
|
SEPOLIA = 11155111
|
||||||
}
|
}
|
||||||
export type NetIdType = NetId | number;
|
export type NetIdType = NetId | number;
|
||||||
export interface RpcUrl {
|
export interface TornadoInstances {
|
||||||
name: string;
|
|
||||||
url: string;
|
|
||||||
}
|
|
||||||
export type RpcUrls = Record<string, RpcUrl>;
|
|
||||||
export interface SubgraphUrl {
|
|
||||||
name: string;
|
|
||||||
url: string;
|
|
||||||
}
|
|
||||||
export type SubgraphUrls = Record<string, SubgraphUrl>;
|
|
||||||
export interface TornadoInstance {
|
|
||||||
instanceAddress: Record<string, string>;
|
instanceAddress: Record<string, string>;
|
||||||
instanceApproval?: boolean;
|
instanceApproval?: boolean;
|
||||||
optionalInstances?: string[];
|
optionalInstances?: string[];
|
||||||
|
isOptional?: boolean;
|
||||||
|
isDisabled?: boolean;
|
||||||
tokenAddress?: string;
|
tokenAddress?: string;
|
||||||
tokenGasLimit?: number;
|
tokenGasLimit?: number;
|
||||||
symbol: string;
|
symbol: string;
|
||||||
decimals: number;
|
decimals: number;
|
||||||
gasLimit?: number;
|
gasLimit?: number;
|
||||||
}
|
}
|
||||||
export type TokenInstances = Record<string, TornadoInstance>;
|
export interface TornadoSingleInstance {
|
||||||
export interface Config {
|
netId: NetId;
|
||||||
nativeCurrency: string;
|
instanceAddress: string;
|
||||||
currencyName: string;
|
instanceApproval?: boolean;
|
||||||
explorerUrl: string;
|
isOptional?: boolean;
|
||||||
merkleTreeHeight: number;
|
isDisabled?: boolean;
|
||||||
emptyElement: string;
|
tokenAddress?: string;
|
||||||
|
tokenGasLimit?: number;
|
||||||
|
currency: string;
|
||||||
|
amount: string;
|
||||||
|
decimals: number;
|
||||||
|
gasLimit?: number;
|
||||||
|
}
|
||||||
|
export type TokenInstances = Record<string, TornadoInstances>;
|
||||||
|
export type SubdomainMap = Record<NetIdType, string>;
|
||||||
|
export interface ConfigParams {
|
||||||
|
netId: NetIdType;
|
||||||
networkName: string;
|
networkName: string;
|
||||||
|
currencyName: string;
|
||||||
|
nativeCurrency?: string;
|
||||||
|
explorerUrl: string;
|
||||||
|
homepageUrl: string;
|
||||||
|
blockTime: number;
|
||||||
deployedBlock: number;
|
deployedBlock: number;
|
||||||
rpcUrls: RpcUrls;
|
merkleTreeHeight?: number;
|
||||||
|
emptyElement?: string;
|
||||||
|
stablecoin: string;
|
||||||
|
multicallContract?: string;
|
||||||
|
routerContract?: string;
|
||||||
|
echoContract?: string;
|
||||||
|
offchainOracleContract?: string;
|
||||||
|
tornContract?: string;
|
||||||
|
governanceContract?: string;
|
||||||
|
stakingRewardsContract?: string;
|
||||||
|
registryContract?: string;
|
||||||
|
tovarishRegistryContract?: string;
|
||||||
|
aggregatorContract?: string;
|
||||||
|
reverseRecordsContract?: string;
|
||||||
|
ovmGasPriceOracleContract?: string;
|
||||||
|
relayerEnsSubdomain: string;
|
||||||
|
tornadoSubgraph?: string;
|
||||||
|
registrySubgraph?: string;
|
||||||
|
governanceSubgraph?: string;
|
||||||
|
subgraphs?: string[];
|
||||||
|
rpcUrls: string[];
|
||||||
|
tokens: TokenInstances;
|
||||||
|
}
|
||||||
|
export declare class Config {
|
||||||
|
netId: NetIdType;
|
||||||
|
networkName: string;
|
||||||
|
currencyName: string;
|
||||||
|
nativeCurrency: string;
|
||||||
|
explorerUrl: string;
|
||||||
|
homepageUrl: string;
|
||||||
|
blockTime: number;
|
||||||
|
deployedBlock: number;
|
||||||
|
merkleTreeHeight?: number;
|
||||||
|
emptyElement?: string;
|
||||||
stablecoin: string;
|
stablecoin: string;
|
||||||
multicallContract: string;
|
multicallContract: string;
|
||||||
routerContract: string;
|
routerContract: string;
|
||||||
@@ -54,52 +102,36 @@ export interface Config {
|
|||||||
governanceContract?: string;
|
governanceContract?: string;
|
||||||
stakingRewardsContract?: string;
|
stakingRewardsContract?: string;
|
||||||
registryContract?: string;
|
registryContract?: string;
|
||||||
|
tovarishRegistryContract?: string;
|
||||||
aggregatorContract?: string;
|
aggregatorContract?: string;
|
||||||
reverseRecordsContract?: string;
|
reverseRecordsContract?: string;
|
||||||
ovmGasPriceOracleContract?: string;
|
ovmGasPriceOracleContract?: string;
|
||||||
|
relayerEnsSubdomain: string;
|
||||||
tornadoSubgraph?: string;
|
tornadoSubgraph?: string;
|
||||||
registrySubgraph?: string;
|
registrySubgraph?: string;
|
||||||
governanceSubgraph?: string;
|
governanceSubgraph?: string;
|
||||||
subgraphs?: SubgraphUrls;
|
subgraphs?: string[];
|
||||||
|
rpcUrls: string[];
|
||||||
tokens: TokenInstances;
|
tokens: TokenInstances;
|
||||||
optionalTokens?: string[];
|
constructor(configParams: ConfigParams);
|
||||||
disabledTokens?: string[];
|
toJSON(): ConfigParams;
|
||||||
relayerEnsSubdomain: string;
|
get allTokens(): string[];
|
||||||
pollInterval: number;
|
get allSymbols(): string[];
|
||||||
constants?: {
|
getInstance(currency: string, amount: string): TornadoSingleInstance;
|
||||||
GOVERNANCE_BLOCK?: number;
|
getInstanceByAddress(instanceAddress: string): TornadoSingleInstance;
|
||||||
NOTE_ACCOUNT_BLOCK?: number;
|
get depositTypes(): Record<string, DepositType>;
|
||||||
ENCRYPTED_NOTES_BLOCK?: number;
|
|
||||||
REGISTRY_BLOCK?: number;
|
|
||||||
MINING_BLOCK_TIME?: number;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
export type networkConfig = Record<NetIdType, Config>;
|
export interface TornadoConfigParams {
|
||||||
export type SubdomainMap = Record<NetIdType, string>;
|
configs?: Record<NetIdType, ConfigParams>;
|
||||||
export declare const defaultConfig: networkConfig;
|
governanceNetwork?: NetIdType;
|
||||||
export declare const enabledChains: NetIdType[];
|
relayerNetwork?: NetIdType;
|
||||||
/**
|
}
|
||||||
* Custom config object to extend default config
|
export declare class TornadoConfig {
|
||||||
*
|
configs: Record<NetIdType, Config>;
|
||||||
* Inspired by getUrlFunc from ethers.js
|
governanceNetwork: NetIdType;
|
||||||
* https://github.com/ethers-io/ethers.js/blob/v6/src.ts/utils/fetch.ts#L59
|
relayerNetwork: NetIdType;
|
||||||
*/
|
constructor(configParams?: TornadoConfigParams);
|
||||||
export declare let customConfig: networkConfig;
|
get chains(): NetIdType[];
|
||||||
/**
|
getConfig(netId: NetIdType): Config;
|
||||||
* Add or override existing network config object
|
}
|
||||||
*
|
export declare const defaultConfig: Record<NetIdType, ConfigParams>;
|
||||||
* Could be also called on the UI hook so that the UI could allow people to use custom privacy pools
|
|
||||||
*/
|
|
||||||
export declare function addNetwork(newConfig: networkConfig): void;
|
|
||||||
export declare function getNetworkConfig(): networkConfig;
|
|
||||||
export declare function getConfig(netId: NetIdType): Config;
|
|
||||||
export declare function getActiveTokens(config: Config): string[];
|
|
||||||
export declare function getInstanceByAddress(config: Config, address: string): {
|
|
||||||
amount: string;
|
|
||||||
currency: string;
|
|
||||||
symbol: string;
|
|
||||||
decimals: number;
|
|
||||||
tokenAddress: string | undefined;
|
|
||||||
} | undefined;
|
|
||||||
export declare function getRelayerEnsSubdomains(): SubdomainMap;
|
|
||||||
export declare function getMultiInstances(netId: NetIdType, config: Config): Record<string, DepositType>;
|
|
||||||
|
|||||||
17
dist/relayerClient.d.ts
vendored
17
dist/relayerClient.d.ts
vendored
@@ -1,4 +1,4 @@
|
|||||||
import { NetIdType, Config } from './networkConfig';
|
import type { NetIdType, TornadoConfig } from './networkConfig';
|
||||||
import { fetchDataOptions } from './providers';
|
import { fetchDataOptions } from './providers';
|
||||||
import type { snarkProofs } from './websnark';
|
import type { snarkProofs } from './websnark';
|
||||||
import type { CachedRelayerInfo } from './events';
|
import type { CachedRelayerInfo } from './events';
|
||||||
@@ -109,23 +109,22 @@ export type RelayerInstanceList = Record<string, {
|
|||||||
export declare function getSupportedInstances(instanceList: RelayerInstanceList): string[];
|
export declare function getSupportedInstances(instanceList: RelayerInstanceList): string[];
|
||||||
export declare function pickWeightedRandomRelayer(relayers: RelayerInfo[]): RelayerInfo;
|
export declare function pickWeightedRandomRelayer(relayers: RelayerInfo[]): RelayerInfo;
|
||||||
export interface RelayerClientConstructor {
|
export interface RelayerClientConstructor {
|
||||||
netId: NetIdType;
|
tornadoConfig: TornadoConfig;
|
||||||
config: Config;
|
|
||||||
fetchDataOptions?: fetchDataOptions;
|
fetchDataOptions?: fetchDataOptions;
|
||||||
}
|
}
|
||||||
export declare class RelayerClient {
|
export declare class RelayerClient {
|
||||||
netId: NetIdType;
|
tornadoConfig: TornadoConfig;
|
||||||
config: Config;
|
|
||||||
selectedRelayer?: RelayerInfo;
|
selectedRelayer?: RelayerInfo;
|
||||||
fetchDataOptions?: fetchDataOptions;
|
fetchDataOptions?: fetchDataOptions;
|
||||||
tovarish: boolean;
|
tovarish: boolean;
|
||||||
constructor({ netId, config, fetchDataOptions }: RelayerClientConstructor);
|
constructor({ tornadoConfig, fetchDataOptions }: RelayerClientConstructor);
|
||||||
askRelayerStatus({ hostname, url, }: {
|
askRelayerStatus({ netId, hostname, url, }: {
|
||||||
|
netId: NetIdType;
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
}): Promise<RelayerStatus>;
|
}): Promise<RelayerStatus>;
|
||||||
filterRelayer(relayer: CachedRelayerInfo): Promise<RelayerInfo | RelayerError | undefined>;
|
filterRelayer(netId: NetIdType, relayer: CachedRelayerInfo): Promise<RelayerInfo | RelayerError | undefined>;
|
||||||
getValidRelayers(relayers: CachedRelayerInfo[]): Promise<{
|
getValidRelayers(netId: NetIdType, relayers: CachedRelayerInfo[]): Promise<{
|
||||||
validRelayers: RelayerInfo[];
|
validRelayers: RelayerInfo[];
|
||||||
invalidRelayers: RelayerError[];
|
invalidRelayers: RelayerError[];
|
||||||
}>;
|
}>;
|
||||||
|
|||||||
6
dist/schemas/status.d.ts
vendored
6
dist/schemas/status.d.ts
vendored
@@ -1,4 +1,4 @@
|
|||||||
import { Config, NetIdType } from '../networkConfig';
|
import { Config } from '../networkConfig';
|
||||||
import { addressSchemaType, bnSchemaType } from '.';
|
import { addressSchemaType, bnSchemaType } from '.';
|
||||||
export interface statusInstanceType {
|
export interface statusInstanceType {
|
||||||
type: string;
|
type: string;
|
||||||
@@ -10,7 +10,7 @@ export interface statusInstanceType {
|
|||||||
};
|
};
|
||||||
tokenAddress?: typeof addressSchemaType;
|
tokenAddress?: typeof addressSchemaType;
|
||||||
symbol?: {
|
symbol?: {
|
||||||
enum: string[];
|
type: string;
|
||||||
};
|
};
|
||||||
decimals: {
|
decimals: {
|
||||||
enum: number[];
|
enum: number[];
|
||||||
@@ -95,4 +95,4 @@ export interface statusSchema {
|
|||||||
};
|
};
|
||||||
required: string[];
|
required: string[];
|
||||||
}
|
}
|
||||||
export declare function getStatusSchema(netId: NetIdType, config: Config, tovarish: boolean): statusSchema;
|
export declare function getStatusSchema(config: Config, tovarish: boolean): statusSchema;
|
||||||
|
|||||||
324379
dist/tornado.umd.js
vendored
324379
dist/tornado.umd.js
vendored
File diff suppressed because one or more lines are too long
6
dist/tornado.umd.min.js
vendored
6
dist/tornado.umd.min.js
vendored
File diff suppressed because one or more lines are too long
14809
dist/tornadoContracts.umd.js
vendored
14809
dist/tornadoContracts.umd.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tornadoContracts.umd.min.js
vendored
2
dist/tornadoContracts.umd.min.js
vendored
File diff suppressed because one or more lines are too long
8
dist/tovarishClient.d.ts
vendored
8
dist/tovarishClient.d.ts
vendored
@@ -1,5 +1,6 @@
|
|||||||
import { RelayerClient, RelayerClientConstructor, RelayerError, RelayerInfo, RelayerStatus } from './relayerClient';
|
import { RelayerClient, RelayerClientConstructor, RelayerError, RelayerInfo, RelayerStatus } from './relayerClient';
|
||||||
import { CachedRelayerInfo, MinimalEvents } from './events';
|
import { CachedRelayerInfo, MinimalEvents } from './events';
|
||||||
|
import { NetIdType } from './networkConfig';
|
||||||
export declare const MAX_TOVARISH_EVENTS = 5000;
|
export declare const MAX_TOVARISH_EVENTS = 5000;
|
||||||
export interface EventsStatus {
|
export interface EventsStatus {
|
||||||
events: number;
|
events: number;
|
||||||
@@ -45,7 +46,8 @@ export interface BaseTovarishEvents<T> {
|
|||||||
export declare class TovarishClient extends RelayerClient {
|
export declare class TovarishClient extends RelayerClient {
|
||||||
selectedRelayer?: TovarishInfo;
|
selectedRelayer?: TovarishInfo;
|
||||||
constructor(clientConstructor: RelayerClientConstructor);
|
constructor(clientConstructor: RelayerClientConstructor);
|
||||||
askRelayerStatus({ hostname, url, }: {
|
askRelayerStatus({ netId, hostname, url, }: {
|
||||||
|
netId: NetIdType;
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
relayerAddress?: string;
|
relayerAddress?: string;
|
||||||
@@ -58,8 +60,8 @@ export declare class TovarishClient extends RelayerClient {
|
|||||||
url?: string;
|
url?: string;
|
||||||
relayerAddress?: string;
|
relayerAddress?: string;
|
||||||
}): Promise<TovarishStatus[]>;
|
}): Promise<TovarishStatus[]>;
|
||||||
filterRelayer(relayer: CachedRelayerInfo): Promise<TovarishInfo | RelayerError | undefined>;
|
filterRelayer(netId: NetIdType, relayer: CachedRelayerInfo): Promise<TovarishInfo | RelayerError | undefined>;
|
||||||
getValidRelayers(relayers: CachedRelayerInfo[]): Promise<{
|
getValidRelayers(netId: NetIdType, relayers: CachedRelayerInfo[]): Promise<{
|
||||||
validRelayers: TovarishInfo[];
|
validRelayers: TovarishInfo[];
|
||||||
invalidRelayers: RelayerError[];
|
invalidRelayers: RelayerError[];
|
||||||
}>;
|
}>;
|
||||||
|
|||||||
58
package.json
58
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tornado-scripts",
|
"name": "tornado-scripts",
|
||||||
"version": "1.0.21",
|
"version": "1.0.23",
|
||||||
"description": "An SDK for building applications on top of Privacy Pools",
|
"description": "An SDK for building applications on top of Privacy Pools",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.mjs",
|
"module": "./dist/index.mjs",
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
"build": "yarn types && yarn build:node && yarn build:web && yarn build:hash",
|
"build": "yarn types && yarn build:node && yarn build:web && yarn build:hash",
|
||||||
"docker:build": "docker build -t tornado-scripts .",
|
"docker:build": "docker build -t tornado-scripts .",
|
||||||
"docker:hash": "docker container run --rm -it --entrypoint cat tornado-scripts /app/dist/hashes.json",
|
"docker:hash": "docker container run --rm -it --entrypoint cat tornado-scripts /app/dist/hashes.json",
|
||||||
"test": "nyc mocha --require ts-node/register --require source-map-support/register --recursive 'test/**/*.ts' --timeout '300000'"
|
"test": "nyc mocha --require ts-node/register --require source-map-support/register --timeout 300000 --recursive test/**/*.ts"
|
||||||
},
|
},
|
||||||
"author": "Tornado Contrib",
|
"author": "Tornado Contrib",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -42,60 +42,60 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ensdomains/content-hash": "2.5.7",
|
"@ensdomains/content-hash": "2.5.7",
|
||||||
"@metamask/eth-sig-util": "^8.1.2",
|
"@metamask/eth-sig-util": "^8.2.0",
|
||||||
"ajv": "^8.17.1",
|
"ajv": "^8.17.1",
|
||||||
"bn.js": "^5.2.1",
|
"bn.js": "^5.2.1",
|
||||||
"circomlibjs": "git+https://github.com/tornadocontrib/circomlibjs.git#2aef7aade8e2b8d103250e4b24c7f1526cf1dd8d",
|
"circomlibjs": "git+https://github.com/tornadocontrib/circomlibjs.git#2aef7aade8e2b8d103250e4b24c7f1526cf1dd8d",
|
||||||
"ethers": "^6.13.4",
|
"ethers": "^6.13.5",
|
||||||
"ffjavascript": "git+https://github.com/tornadocontrib/ffjavascript.git#fc766f09818d46967d1329c0fc8e361d8b349109",
|
"ffjavascript": "git+https://github.com/tornadocontrib/ffjavascript.git#fc766f09818d46967d1329c0fc8e361d8b349109",
|
||||||
"fflate": "^0.8.2",
|
"fflate": "^0.8.2",
|
||||||
"fixed-merkle-tree": "0.7.3",
|
"fixed-merkle-tree": "0.7.3",
|
||||||
"snarkjs": "git+https://github.com/tornadocontrib/snarkjs.git#2c964b3fe6019e057acab04cc17705d1f7fdaf9a",
|
"snarkjs": "git+https://github.com/tornadocontrib/snarkjs.git#2c964b3fe6019e057acab04cc17705d1f7fdaf9a",
|
||||||
"tornado-contracts": "git+https://github.com/tornadocontrib/tornado-contracts.git#9be1e1c308ae891e939944b2220d9e2810e579f5",
|
"tornado-contracts": "git+https://github.com/tornadocontrib/tornado-contracts.git#a1c8fbd2919996a642a7de1abec86548ff64449b",
|
||||||
"websnark": "git+https://github.com/tornadocontrib/websnark.git#e5a79cca905d1ffb61a69739492be58d438c9f17"
|
"websnark": "git+https://github.com/tornadocontrib/websnark.git#e5a79cca905d1ffb61a69739492be58d438c9f17"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nomicfoundation/hardhat-chai-matchers": "^2.0.8",
|
"@nomicfoundation/hardhat-chai-matchers": "^2.0.8",
|
||||||
"@nomicfoundation/hardhat-ethers": "^3.0.8",
|
"@nomicfoundation/hardhat-ethers": "^3.0.8",
|
||||||
"@nomicfoundation/hardhat-ignition": "^0.15.9",
|
"@nomicfoundation/hardhat-ignition": "^0.15.11",
|
||||||
"@nomicfoundation/hardhat-ignition-ethers": "^0.15.9",
|
"@nomicfoundation/hardhat-ignition-ethers": "^0.15.11",
|
||||||
"@nomicfoundation/hardhat-network-helpers": "^1.0.12",
|
"@nomicfoundation/hardhat-network-helpers": "^1.0.12",
|
||||||
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
|
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
|
||||||
"@nomicfoundation/hardhat-verify": "^2.0.12",
|
"@nomicfoundation/hardhat-verify": "^2.0.13",
|
||||||
"@rollup/plugin-commonjs": "^28.0.2",
|
"@rollup/plugin-commonjs": "^28.0.3",
|
||||||
"@rollup/plugin-json": "^6.1.0",
|
"@rollup/plugin-json": "^6.1.0",
|
||||||
"@rollup/plugin-node-resolve": "^16.0.0",
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||||
"@typechain/ethers-v6": "^0.5.1",
|
"@typechain/ethers-v6": "^0.5.1",
|
||||||
"@typechain/hardhat": "^9.1.0",
|
"@typechain/hardhat": "^9.1.0",
|
||||||
"@types/bn.js": "^5.1.6",
|
"@types/bn.js": "^5.1.6",
|
||||||
"@types/chai": "^5.0.1",
|
"@types/chai": "^5.2.1",
|
||||||
"@types/circomlibjs": "^0.1.6",
|
"@types/circomlibjs": "^0.1.6",
|
||||||
"@types/mocha": "^10.0.10",
|
"@types/mocha": "^10.0.10",
|
||||||
"@types/node": "^22.10.2",
|
"@types/node": "^22.14.1",
|
||||||
"chai": "^4.5.0",
|
"chai": "^4.5.0",
|
||||||
"esbuild-loader": "^4.2.2",
|
"esbuild-loader": "^4.3.0",
|
||||||
"eslint": "^9.17.0",
|
"eslint": "^9.24.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^10.1.2",
|
||||||
"eslint-import-resolver-typescript": "^3.7.0",
|
"eslint-import-resolver-typescript": "^4.3.2",
|
||||||
"eslint-plugin-import": "^2.31.0",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.6",
|
||||||
"fetch-mock": "^12.2.0",
|
"fetch-mock": "^12.5.2",
|
||||||
"hardhat": "^2.22.17",
|
"hardhat": "^2.23.0",
|
||||||
"hardhat-gas-reporter": "^2.2.2",
|
"hardhat-gas-reporter": "^2.2.3",
|
||||||
"idb": "^8.0.1",
|
"idb": "^8.0.2",
|
||||||
"mocha": "^11.0.1",
|
"mocha": "^11.1.0",
|
||||||
"node-polyfill-webpack-plugin": "^4.1.0",
|
"node-polyfill-webpack-plugin": "^4.1.0",
|
||||||
"nyc": "^17.1.0",
|
"nyc": "^17.1.0",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.5.3",
|
||||||
"rollup": "^4.29.1",
|
"rollup": "^4.40.0",
|
||||||
"rollup-plugin-esbuild": "^6.1.1",
|
"rollup-plugin-esbuild": "^6.2.1",
|
||||||
"solidity-coverage": "^0.8.14",
|
"solidity-coverage": "^0.8.15",
|
||||||
"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.7.2",
|
"typescript": "^5.8.3",
|
||||||
"typescript-eslint": "^8.18.2",
|
"typescript-eslint": "^8.30.1",
|
||||||
"webpack": "^5.97.1",
|
"webpack": "^5.99.5",
|
||||||
"webpack-cli": "^6.0.1"
|
"webpack-cli": "^6.0.1"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {
|
|||||||
EventLog,
|
EventLog,
|
||||||
TransactionResponse,
|
TransactionResponse,
|
||||||
getAddress,
|
getAddress,
|
||||||
namehash,
|
|
||||||
formatEther,
|
formatEther,
|
||||||
AbiCoder,
|
AbiCoder,
|
||||||
dataLength,
|
dataLength,
|
||||||
@@ -18,8 +17,8 @@ import {
|
|||||||
Governance,
|
Governance,
|
||||||
RelayerRegistry,
|
RelayerRegistry,
|
||||||
Echoer,
|
Echoer,
|
||||||
Aggregator,
|
|
||||||
Tornado__factory,
|
Tornado__factory,
|
||||||
|
TovarishAggregator,
|
||||||
} from 'tornado-contracts';
|
} from 'tornado-contracts';
|
||||||
|
|
||||||
import type { MerkleTree } from 'fixed-merkle-tree';
|
import type { MerkleTree } from 'fixed-merkle-tree';
|
||||||
@@ -31,8 +30,8 @@ import {
|
|||||||
BatchBlockOnProgress,
|
BatchBlockOnProgress,
|
||||||
} from '../batch';
|
} from '../batch';
|
||||||
|
|
||||||
import { fetchData, fetchDataOptions } from '../providers';
|
import { fetchDataOptions } from '../providers';
|
||||||
import { enabledChains, type NetIdType, type SubdomainMap } from '../networkConfig';
|
import { TornadoConfig, type NetIdType, type SubdomainMap } from '../networkConfig';
|
||||||
import { RelayerParams, MIN_STAKE_BALANCE } from '../relayerClient';
|
import { RelayerParams, MIN_STAKE_BALANCE } from '../relayerClient';
|
||||||
import type { TovarishClient } from '../tovarishClient';
|
import type { TovarishClient } from '../tovarishClient';
|
||||||
|
|
||||||
@@ -816,13 +815,13 @@ export interface GovernanceVotes extends GovernanceVotedEvents {
|
|||||||
|
|
||||||
export interface BaseGovernanceServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
export interface BaseGovernanceServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||||
Governance: Governance;
|
Governance: Governance;
|
||||||
Aggregator: Aggregator;
|
Aggregator: TovarishAggregator;
|
||||||
ReverseRecords: ReverseRecords;
|
ReverseRecords: ReverseRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents> {
|
export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents> {
|
||||||
Governance: Governance;
|
Governance: Governance;
|
||||||
Aggregator: Aggregator;
|
Aggregator: TovarishAggregator;
|
||||||
ReverseRecords: ReverseRecords;
|
ReverseRecords: ReverseRecords;
|
||||||
|
|
||||||
batchTransactionService: BatchTransactionService;
|
batchTransactionService: BatchTransactionService;
|
||||||
@@ -950,7 +949,7 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
|
|
||||||
const [QUORUM_VOTES, proposalStatus, proposerNameRecords] = await Promise.all([
|
const [QUORUM_VOTES, proposalStatus, proposerNameRecords] = await Promise.all([
|
||||||
this.Governance.QUORUM_VOTES(),
|
this.Governance.QUORUM_VOTES(),
|
||||||
this.Aggregator.getAllProposals(this.Governance.target),
|
this.Aggregator.getAllProposals(),
|
||||||
this.ReverseRecords.getNames(allProposers),
|
this.ReverseRecords.getNames(allProposers),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -1061,7 +1060,7 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [balances, uniqNameRecords] = await Promise.all([
|
const [balances, uniqNameRecords] = await Promise.all([
|
||||||
this.Aggregator.getGovernanceBalances(this.Governance.target, uniq),
|
this.Aggregator.getGovernanceBalances(uniq),
|
||||||
this.ReverseRecords.getNames(uniq),
|
this.ReverseRecords.getNames(uniq),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -1086,28 +1085,6 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getTovarishNetworks(registryService: BaseRegistryService, relayers: CachedRelayerInfo[]) {
|
|
||||||
await Promise.all(
|
|
||||||
relayers
|
|
||||||
.filter((r) => r.tovarishHost)
|
|
||||||
.map(async (relayer) => {
|
|
||||||
try {
|
|
||||||
relayer.tovarishNetworks = await fetchData(relayer.tovarishHost as string, {
|
|
||||||
...registryService.fetchDataOptions,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
timeout: 30000,
|
|
||||||
maxRetry: registryService.fetchDataOptions?.dispatcher ? 2 : 0,
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
// Ignore error and disable relayer
|
|
||||||
relayer.tovarishNetworks = [];
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Essential params:
|
* Essential params:
|
||||||
* ensName, relayerAddress, hostnames
|
* ensName, relayerAddress, hostnames
|
||||||
@@ -1115,55 +1092,26 @@ export async function getTovarishNetworks(registryService: BaseRegistryService,
|
|||||||
*/
|
*/
|
||||||
export interface CachedRelayerInfo extends RelayerParams {
|
export interface CachedRelayerInfo extends RelayerParams {
|
||||||
isRegistered?: boolean;
|
isRegistered?: boolean;
|
||||||
registeredAddress?: string;
|
isPrior?: boolean;
|
||||||
stakeBalance?: string;
|
stakeBalance?: string;
|
||||||
hostnames: SubdomainMap;
|
hostnames: SubdomainMap;
|
||||||
tovarishHost?: string;
|
tovarishHost?: string;
|
||||||
tovarishNetworks?: number[];
|
tovarishNetworks?: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Static relayer provided by tornadowithdraw.eth
|
|
||||||
* This relayer isn't compatible with the current UI (tornadocash.eth) and only works as experimental mode
|
|
||||||
* Once DAO approves changes to UI to support new Tovarish Relayer software register relayer and remove static list
|
|
||||||
*/
|
|
||||||
const staticRelayers: CachedRelayerInfo[] = [
|
|
||||||
{
|
|
||||||
ensName: 'tornadowithdraw.eth',
|
|
||||||
relayerAddress: '0x40c3d1656a26C9266f4A10fed0D87EFf79F54E64',
|
|
||||||
hostnames: {},
|
|
||||||
tovarishHost: 'tornadowithdraw.com',
|
|
||||||
tovarishNetworks: enabledChains,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ensName: 'rpc.tornadowithdraw.eth',
|
|
||||||
relayerAddress: '0xFF787B7A5cd8a88508361E3B7bcE791Aa2796526',
|
|
||||||
hostnames: {},
|
|
||||||
tovarishHost: 'tornadocash-rpc.com',
|
|
||||||
tovarishNetworks: enabledChains,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export interface CachedRelayers {
|
|
||||||
lastBlock: number;
|
|
||||||
timestamp: number;
|
|
||||||
relayers: CachedRelayerInfo[];
|
|
||||||
fromCache?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BaseRegistryServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
export interface BaseRegistryServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||||
|
tornadoConfig: TornadoConfig;
|
||||||
RelayerRegistry: RelayerRegistry;
|
RelayerRegistry: RelayerRegistry;
|
||||||
Aggregator: Aggregator;
|
Aggregator: TovarishAggregator;
|
||||||
relayerEnsSubdomains: SubdomainMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BaseRegistryService extends BaseEventsService<AllRelayerRegistryEvents> {
|
export class BaseRegistryService extends BaseEventsService<AllRelayerRegistryEvents> {
|
||||||
Aggregator: Aggregator;
|
tornadoConfig: TornadoConfig;
|
||||||
relayerEnsSubdomains: SubdomainMap;
|
Aggregator: TovarishAggregator;
|
||||||
updateInterval: number;
|
updateInterval: number;
|
||||||
|
|
||||||
constructor(serviceConstructor: BaseRegistryServiceConstructor) {
|
constructor(serviceConstructor: BaseRegistryServiceConstructor) {
|
||||||
const { RelayerRegistry: contract, Aggregator, relayerEnsSubdomains } = serviceConstructor;
|
const { RelayerRegistry: contract, tornadoConfig, Aggregator } = serviceConstructor;
|
||||||
|
|
||||||
super({
|
super({
|
||||||
...serviceConstructor,
|
...serviceConstructor,
|
||||||
@@ -1171,8 +1119,8 @@ export class BaseRegistryService extends BaseEventsService<AllRelayerRegistryEve
|
|||||||
type: '*',
|
type: '*',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.tornadoConfig = tornadoConfig;
|
||||||
this.Aggregator = Aggregator;
|
this.Aggregator = Aggregator;
|
||||||
this.relayerEnsSubdomains = relayerEnsSubdomains;
|
|
||||||
|
|
||||||
this.updateInterval = 86400;
|
this.updateInterval = 86400;
|
||||||
}
|
}
|
||||||
@@ -1249,69 +1197,38 @@ export class BaseRegistryService extends BaseEventsService<AllRelayerRegistryEve
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async getLatestRelayers(knownRelayers?: string[]): Promise<CachedRelayerInfo[]> {
|
||||||
* Get saved or cached relayers
|
const newRelayers: string[] = [];
|
||||||
*/
|
|
||||||
async getRelayersFromDB(): Promise<CachedRelayers> {
|
|
||||||
return {
|
|
||||||
lastBlock: 0,
|
|
||||||
timestamp: 0,
|
|
||||||
relayers: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (knownRelayers?.length) {
|
||||||
* Relayers from remote cache (Either from local cache, CDN, or from IPFS)
|
const { events: allEvents } = await this.updateEvents();
|
||||||
*/
|
|
||||||
async getRelayersFromCache(): Promise<CachedRelayers> {
|
|
||||||
return {
|
|
||||||
lastBlock: 0,
|
|
||||||
timestamp: 0,
|
|
||||||
relayers: [],
|
|
||||||
fromCache: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async getSavedRelayers(): Promise<CachedRelayers> {
|
|
||||||
let cachedRelayers = await this.getRelayersFromDB();
|
|
||||||
|
|
||||||
if (!cachedRelayers || !cachedRelayers.relayers.length) {
|
|
||||||
cachedRelayers = await this.getRelayersFromCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
return cachedRelayers;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getLatestRelayers(): Promise<CachedRelayers> {
|
|
||||||
const { events: allEvents, lastBlock } = await this.updateEvents();
|
|
||||||
|
|
||||||
const events = allEvents.filter((e) => e.event === 'RelayerRegistered') as RelayerRegisteredEvents[];
|
const events = allEvents.filter((e) => e.event === 'RelayerRegistered') as RelayerRegisteredEvents[];
|
||||||
|
|
||||||
const subdomains = Object.values(this.relayerEnsSubdomains);
|
for (const { ensName } of events) {
|
||||||
|
if (!newRelayers.includes(ensName) && !knownRelayers?.includes(ensName)) {
|
||||||
const registerSet = new Set();
|
newRelayers.push(ensName);
|
||||||
|
}
|
||||||
const uniqueRegisters = events.filter(({ ensName }) => {
|
}
|
||||||
if (!registerSet.has(ensName)) {
|
|
||||||
registerSet.add(ensName);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
const relayerNameHashes = uniqueRegisters.map((r) => namehash(r.ensName));
|
const [chains, relayersData] = await Promise.all([
|
||||||
|
this.Aggregator.getChainIds.staticCall(),
|
||||||
const [relayersData, timestamp] = await Promise.all([
|
this.Aggregator.relayersData.staticCall(newRelayers),
|
||||||
this.Aggregator.relayersData.staticCall(relayerNameHashes, subdomains.concat('tovarish-relayer')),
|
|
||||||
this.provider.getBlock(lastBlock).then((b) => Number(b?.timestamp)),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const relayers = relayersData
|
const relayers = relayersData
|
||||||
.map(({ owner, balance: stakeBalance, records, isRegistered }, index) => {
|
.map(
|
||||||
const { ensName, relayerAddress } = uniqueRegisters[index];
|
({
|
||||||
|
ensName,
|
||||||
let tovarishHost = undefined;
|
owner,
|
||||||
|
balance: stakeBalance,
|
||||||
|
isRegistered,
|
||||||
|
isPrior,
|
||||||
|
tovarishHost,
|
||||||
|
tovarishChains,
|
||||||
|
records,
|
||||||
|
}) => {
|
||||||
const hostnames = records.reduce((acc, record, recordIndex) => {
|
const hostnames = records.reduce((acc, record, recordIndex) => {
|
||||||
if (record) {
|
if (record) {
|
||||||
// tovarish-relayer.relayer.eth
|
// tovarish-relayer.relayer.eth
|
||||||
@@ -1320,70 +1237,60 @@ export class BaseRegistryService extends BaseEventsService<AllRelayerRegistryEve
|
|||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
acc[Number(Object.keys(this.relayerEnsSubdomains)[recordIndex])] = record;
|
acc[Number(chains[recordIndex])] = record;
|
||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as SubdomainMap);
|
}, {} as SubdomainMap);
|
||||||
|
|
||||||
const hasMinBalance = stakeBalance >= MIN_STAKE_BALANCE;
|
const hasMinBalance = stakeBalance >= MIN_STAKE_BALANCE;
|
||||||
|
|
||||||
const preCondition = Object.keys(hostnames).length && isRegistered && hasMinBalance;
|
const tovarishNetworks = [
|
||||||
|
...new Set(
|
||||||
|
tovarishChains
|
||||||
|
.split(',')
|
||||||
|
.map((c) => Number(c))
|
||||||
|
.filter((c) => c && this.tornadoConfig.chains.includes(c)),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
const preCondition =
|
||||||
|
(isRegistered && hasMinBalance && Object.keys(hostnames).length) ||
|
||||||
|
(tovarishHost.length && tovarishNetworks.length);
|
||||||
|
|
||||||
if (preCondition) {
|
if (preCondition) {
|
||||||
return {
|
return {
|
||||||
ensName,
|
ensName,
|
||||||
relayerAddress: owner,
|
relayerAddress: owner,
|
||||||
registeredAddress: owner !== relayerAddress ? relayerAddress : undefined,
|
isPrior,
|
||||||
isRegistered,
|
isRegistered,
|
||||||
stakeBalance: formatEther(stakeBalance),
|
stakeBalance: formatEther(stakeBalance),
|
||||||
hostnames,
|
hostnames,
|
||||||
tovarishHost,
|
tovarishHost,
|
||||||
|
tovarishNetworks,
|
||||||
} as CachedRelayerInfo;
|
} as CachedRelayerInfo;
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.filter((r) => r) as CachedRelayerInfo[];
|
.filter((r) => r) as CachedRelayerInfo[];
|
||||||
|
|
||||||
await getTovarishNetworks(this, relayers);
|
const sortedRelayers = relayers.sort((a, b) => {
|
||||||
|
// Scoring => isTovarishRelayer => hasMoreStakedBalance
|
||||||
|
// When it is tovarish relayer, it will compare with staked balance as well
|
||||||
|
const getPriorityScore = (i: CachedRelayerInfo) => (i.tovarishHost?.length || 0) + (i.isPrior ? 1 : 0);
|
||||||
|
|
||||||
const allRelayers = [...staticRelayers, ...relayers];
|
const [aScore, bScore] = [getPriorityScore(a), getPriorityScore(b)];
|
||||||
const tovarishRelayers = allRelayers.filter((r) => r.tovarishHost);
|
|
||||||
const classicRelayers = allRelayers.filter((r) => !r.tovarishHost);
|
|
||||||
|
|
||||||
return {
|
if (aScore === bScore) {
|
||||||
lastBlock,
|
// Sort by staked balance
|
||||||
timestamp,
|
const [aBalance, bBalance] = [Number(a.stakeBalance || 0), Number(b.stakeBalance || 0)];
|
||||||
relayers: [...tovarishRelayers, ...classicRelayers],
|
|
||||||
};
|
return bBalance - aBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return bScore - aScore;
|
||||||
* Handle saving relayers
|
});
|
||||||
*/
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
async saveRelayers({ lastBlock, timestamp, relayers }: CachedRelayers) {}
|
|
||||||
|
|
||||||
/**
|
return sortedRelayers;
|
||||||
* Get cached or latest relayer and save to local
|
|
||||||
*/
|
|
||||||
async updateRelayers(): Promise<CachedRelayers> {
|
|
||||||
// eslint-disable-next-line prefer-const
|
|
||||||
let { lastBlock, timestamp, relayers, fromCache } = await this.getSavedRelayers();
|
|
||||||
|
|
||||||
let shouldSave = fromCache ?? false;
|
|
||||||
|
|
||||||
if (!relayers.length || timestamp + this.updateInterval < Math.floor(Date.now() / 1000)) {
|
|
||||||
console.log('\nUpdating relayers from registry\n');
|
|
||||||
|
|
||||||
({ lastBlock, timestamp, relayers } = await this.getLatestRelayers());
|
|
||||||
|
|
||||||
shouldSave = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldSave) {
|
|
||||||
await this.saveRelayers({ lastBlock, timestamp, relayers });
|
|
||||||
}
|
|
||||||
|
|
||||||
return { lastBlock, timestamp, relayers };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { downloadZip } from '../zip';
|
import { downloadZip } from '../zip';
|
||||||
import { IndexedDB } from '../idb';
|
import { IndexedDB } from '../idb';
|
||||||
|
|
||||||
import { bytesToBase64, digest } from '../utils';
|
|
||||||
import { fetchData } from '../providers';
|
|
||||||
import {
|
import {
|
||||||
BaseTornadoService,
|
BaseTornadoService,
|
||||||
BaseTornadoServiceConstructor,
|
BaseTornadoServiceConstructor,
|
||||||
@@ -16,7 +14,6 @@ import {
|
|||||||
BaseRegistryServiceConstructor,
|
BaseRegistryServiceConstructor,
|
||||||
BaseRevenueService,
|
BaseRevenueService,
|
||||||
BaseRevenueServiceConstructor,
|
BaseRevenueServiceConstructor,
|
||||||
CachedRelayers,
|
|
||||||
BaseMultiTornadoService,
|
BaseMultiTornadoService,
|
||||||
BaseMultiTornadoServiceConstructor,
|
BaseMultiTornadoServiceConstructor,
|
||||||
} from './base';
|
} from './base';
|
||||||
@@ -403,7 +400,6 @@ export class DBRegistryService extends BaseRegistryService {
|
|||||||
idb: IndexedDB;
|
idb: IndexedDB;
|
||||||
|
|
||||||
zipDigest?: string;
|
zipDigest?: string;
|
||||||
relayerJsonDigest?: string;
|
|
||||||
|
|
||||||
constructor(params: DBRegistryServiceConstructor) {
|
constructor(params: DBRegistryServiceConstructor) {
|
||||||
super(params);
|
super(params);
|
||||||
@@ -439,78 +435,6 @@ export class DBRegistryService extends BaseRegistryService {
|
|||||||
lastBlock,
|
lastBlock,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRelayersFromDB(): Promise<CachedRelayers> {
|
|
||||||
try {
|
|
||||||
const allCachedRelayers = await this.idb.getAll<CachedRelayers[]>({
|
|
||||||
storeName: `relayers_${this.netId}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!allCachedRelayers?.length) {
|
|
||||||
return {
|
|
||||||
lastBlock: 0,
|
|
||||||
timestamp: 0,
|
|
||||||
relayers: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return allCachedRelayers.slice(-1)[0];
|
|
||||||
} catch (err) {
|
|
||||||
console.log('Method getRelayersFromDB has error');
|
|
||||||
console.log(err);
|
|
||||||
|
|
||||||
return {
|
|
||||||
lastBlock: 0,
|
|
||||||
timestamp: 0,
|
|
||||||
relayers: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRelayersFromCache(): Promise<CachedRelayers> {
|
|
||||||
const url = `${this.staticUrl}/relayers.json`;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const resp = await fetchData<Response>(url, {
|
|
||||||
method: 'GET',
|
|
||||||
returnResponse: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = new Uint8Array(await resp.arrayBuffer());
|
|
||||||
|
|
||||||
if (this.relayerJsonDigest) {
|
|
||||||
const hash = 'sha384-' + bytesToBase64(await digest(data));
|
|
||||||
|
|
||||||
if (hash !== this.relayerJsonDigest) {
|
|
||||||
const errMsg = `Invalid digest hash for ${url}, wants ${this.relayerJsonDigest} has ${hash}`;
|
|
||||||
throw new Error(errMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return JSON.parse(new TextDecoder().decode(data)) as CachedRelayers;
|
|
||||||
} catch (err) {
|
|
||||||
console.log('Method getRelayersFromCache has error');
|
|
||||||
console.log(err);
|
|
||||||
|
|
||||||
return {
|
|
||||||
lastBlock: 0,
|
|
||||||
timestamp: 0,
|
|
||||||
relayers: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async saveRelayers(cachedRelayers: CachedRelayers): Promise<void> {
|
|
||||||
try {
|
|
||||||
await this.idb.putItem({
|
|
||||||
data: cachedRelayers,
|
|
||||||
storeName: `relayers_${this.netId}`,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.log('Method saveRelayers has error');
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DBRevenueServiceConstructor extends BaseRevenueServiceConstructor {
|
export interface DBRevenueServiceConstructor extends BaseRevenueServiceConstructor {
|
||||||
|
|||||||
19
src/idb.ts
19
src/idb.ts
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any, import/no-duplicates */
|
/* eslint-disable @typescript-eslint/no-explicit-any, import/no-duplicates */
|
||||||
import type * as idb from 'idb';
|
import type * as idb from 'idb';
|
||||||
import type { OpenDBCallbacks, IDBPDatabase } from 'idb';
|
import type { OpenDBCallbacks, IDBPDatabase } from 'idb';
|
||||||
import { getConfig, NetIdType } from './networkConfig';
|
import type { NetIdType, TornadoConfig } from './networkConfig';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@@ -321,9 +321,9 @@ export class IndexedDB {
|
|||||||
/**
|
/**
|
||||||
* Should check if DB is initialized well
|
* Should check if DB is initialized well
|
||||||
*/
|
*/
|
||||||
export async function getIndexedDB(netId?: NetIdType) {
|
export async function getIndexedDB(netId?: NetIdType, tornadoConfig?: TornadoConfig) {
|
||||||
// key-value db for settings
|
// key-value db for settings
|
||||||
if (!netId) {
|
if (!netId || !tornadoConfig) {
|
||||||
const idb = new IndexedDB({ dbName: 'tornado-scripts' });
|
const idb = new IndexedDB({ dbName: 'tornado-scripts' });
|
||||||
await idb.initDB();
|
await idb.initDB();
|
||||||
return idb;
|
return idb;
|
||||||
@@ -370,7 +370,7 @@ export async function getIndexedDB(netId?: NetIdType) {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const { tokens, nativeCurrency, registryContract, governanceContract } = getConfig(netId);
|
const { tokens, nativeCurrency, registryContract, governanceContract } = tornadoConfig.getConfig(netId);
|
||||||
|
|
||||||
const stores = [...defaultState];
|
const stores = [...defaultState];
|
||||||
|
|
||||||
@@ -387,17 +387,6 @@ export async function getIndexedDB(netId?: NetIdType) {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
stores.push({
|
|
||||||
name: `relayers_${netId}`,
|
|
||||||
keyPath: 'timestamp',
|
|
||||||
indexes: [
|
|
||||||
{
|
|
||||||
name: 'timestamp',
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
stores.push({
|
stores.push({
|
||||||
name: `revenue_${netId}`,
|
name: `revenue_${netId}`,
|
||||||
keyPath: 'timestamp',
|
keyPath: 'timestamp',
|
||||||
|
|||||||
20
src/ip.ts
20
src/ip.ts
@@ -15,3 +15,23 @@ export function fetchIp(ipEcho: string, fetchOptions?: fetchDataOptions) {
|
|||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 🖕
|
||||||
|
export interface IPResultFuck {
|
||||||
|
YourFuckingIPAddress: string;
|
||||||
|
YourFuckingLocation: string;
|
||||||
|
YourFuckingHostname: string;
|
||||||
|
YourFuckingISP: string;
|
||||||
|
YourFuckingTorExit: boolean;
|
||||||
|
YourFuckingCity?: string;
|
||||||
|
YourFuckingCountry: string;
|
||||||
|
YourFuckingCountryCode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetchFuckingIp(ipFuck = 'https://myip.wtf/json', fetchOptions?: fetchDataOptions) {
|
||||||
|
return fetchData<IPResultFuck>(ipFuck, {
|
||||||
|
...(fetchOptions || {}),
|
||||||
|
method: 'GET',
|
||||||
|
timeout: 30000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -263,7 +263,7 @@ export function getProviderWithNetId(
|
|||||||
config: Config,
|
config: Config,
|
||||||
fetchOptions?: getProviderOptions,
|
fetchOptions?: getProviderOptions,
|
||||||
): JsonRpcProvider {
|
): JsonRpcProvider {
|
||||||
const { networkName, reverseRecordsContract, pollInterval } = config;
|
const { networkName, reverseRecordsContract, blockTime } = config;
|
||||||
const hasEns = Boolean(reverseRecordsContract);
|
const hasEns = Boolean(reverseRecordsContract);
|
||||||
|
|
||||||
const fetchReq = new FetchRequest(rpcUrl);
|
const fetchReq = new FetchRequest(rpcUrl);
|
||||||
@@ -276,7 +276,7 @@ export function getProviderWithNetId(
|
|||||||
|
|
||||||
const provider = new JsonRpcProvider(fetchReq, staticNetwork, {
|
const provider = new JsonRpcProvider(fetchReq, staticNetwork, {
|
||||||
staticNetwork,
|
staticNetwork,
|
||||||
pollingInterval: fetchOptions?.pollingInterval || pollInterval * 1000,
|
pollingInterval: fetchOptions?.pollingInterval || blockTime * 1000,
|
||||||
});
|
});
|
||||||
|
|
||||||
return provider;
|
return provider;
|
||||||
@@ -295,11 +295,16 @@ export const populateTransaction = async (
|
|||||||
throw new Error(errMsg);
|
throw new Error(errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [feeData, nonce] = await Promise.all([
|
const [chainId, feeData, nonce] = await Promise.all([
|
||||||
|
tx.chainId || tx.chainId === 0n ? undefined : provider.getNetwork().then((n) => Number(n.chainId)),
|
||||||
tx.maxFeePerGas || tx.gasPrice ? undefined : provider.getFeeData(),
|
tx.maxFeePerGas || tx.gasPrice ? undefined : provider.getFeeData(),
|
||||||
tx.nonce || tx.nonce === 0 ? undefined : provider.getTransactionCount(signer.address, 'pending'),
|
tx.nonce || tx.nonce === 0 ? undefined : provider.getTransactionCount(signer.address, 'pending'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (chainId) {
|
||||||
|
tx.chainId = chainId;
|
||||||
|
}
|
||||||
|
|
||||||
if (feeData) {
|
if (feeData) {
|
||||||
// EIP-1559
|
// EIP-1559
|
||||||
if (feeData.maxFeePerGas) {
|
if (feeData.maxFeePerGas) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { getAddress, parseEther } from 'ethers';
|
import { getAddress, parseEther } from 'ethers';
|
||||||
import { sleep } from './utils';
|
import { sleep } from './utils';
|
||||||
import { NetIdType, Config } from './networkConfig';
|
import type { NetIdType, TornadoConfig } from './networkConfig';
|
||||||
import { fetchData, fetchDataOptions } from './providers';
|
import { fetchData, fetchDataOptions } from './providers';
|
||||||
import { ajv, jobsSchema, jobRequestSchema, getStatusSchema } from './schemas';
|
import { ajv, jobsSchema, jobRequestSchema, getStatusSchema } from './schemas';
|
||||||
import type { snarkProofs } from './websnark';
|
import type { snarkProofs } from './websnark';
|
||||||
@@ -174,29 +174,28 @@ export function pickWeightedRandomRelayer(relayers: RelayerInfo[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface RelayerClientConstructor {
|
export interface RelayerClientConstructor {
|
||||||
netId: NetIdType;
|
tornadoConfig: TornadoConfig;
|
||||||
config: Config;
|
|
||||||
fetchDataOptions?: fetchDataOptions;
|
fetchDataOptions?: fetchDataOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RelayerClient {
|
export class RelayerClient {
|
||||||
netId: NetIdType;
|
tornadoConfig: TornadoConfig;
|
||||||
config: Config;
|
|
||||||
selectedRelayer?: RelayerInfo;
|
selectedRelayer?: RelayerInfo;
|
||||||
fetchDataOptions?: fetchDataOptions;
|
fetchDataOptions?: fetchDataOptions;
|
||||||
tovarish: boolean;
|
tovarish: boolean;
|
||||||
|
|
||||||
constructor({ netId, config, fetchDataOptions }: RelayerClientConstructor) {
|
constructor({ tornadoConfig, fetchDataOptions }: RelayerClientConstructor) {
|
||||||
this.netId = netId;
|
this.tornadoConfig = tornadoConfig;
|
||||||
this.config = config;
|
|
||||||
this.fetchDataOptions = fetchDataOptions;
|
this.fetchDataOptions = fetchDataOptions;
|
||||||
this.tovarish = false;
|
this.tovarish = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async askRelayerStatus({
|
async askRelayerStatus({
|
||||||
|
netId,
|
||||||
hostname,
|
hostname,
|
||||||
url,
|
url,
|
||||||
}: {
|
}: {
|
||||||
|
netId: NetIdType;
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
// optional url if entered manually
|
// optional url if entered manually
|
||||||
url?: string;
|
url?: string;
|
||||||
@@ -218,7 +217,9 @@ export class RelayerClient {
|
|||||||
maxRetry: this.fetchDataOptions?.dispatcher ? 2 : 0,
|
maxRetry: this.fetchDataOptions?.dispatcher ? 2 : 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const statusValidator = ajv.compile(getStatusSchema(this.netId, this.config, this.tovarish));
|
const config = this.tornadoConfig.getConfig(netId);
|
||||||
|
|
||||||
|
const statusValidator = ajv.compile(getStatusSchema(config, this.tovarish));
|
||||||
|
|
||||||
if (!statusValidator(rawStatus)) {
|
if (!statusValidator(rawStatus)) {
|
||||||
throw new Error('Invalid status schema');
|
throw new Error('Invalid status schema');
|
||||||
@@ -233,7 +234,7 @@ export class RelayerClient {
|
|||||||
throw new Error('Withdrawal queue is overloaded');
|
throw new Error('Withdrawal queue is overloaded');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.netId !== this.netId) {
|
if (status.netId !== netId) {
|
||||||
throw new Error('This relayer serves a different network');
|
throw new Error('This relayer serves a different network');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,8 +247,8 @@ export class RelayerClient {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
async filterRelayer(relayer: CachedRelayerInfo): Promise<RelayerInfo | RelayerError | undefined> {
|
async filterRelayer(netId: NetIdType, relayer: CachedRelayerInfo): Promise<RelayerInfo | RelayerError | undefined> {
|
||||||
const hostname = relayer.hostnames[this.netId];
|
const hostname = relayer.hostnames[netId];
|
||||||
const { ensName, relayerAddress } = relayer;
|
const { ensName, relayerAddress } = relayer;
|
||||||
|
|
||||||
if (!hostname) {
|
if (!hostname) {
|
||||||
@@ -256,6 +257,7 @@ export class RelayerClient {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const status = await this.askRelayerStatus({
|
const status = await this.askRelayerStatus({
|
||||||
|
netId,
|
||||||
hostname,
|
hostname,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -284,13 +286,16 @@ export class RelayerClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getValidRelayers(relayers: CachedRelayerInfo[]): Promise<{
|
async getValidRelayers(
|
||||||
|
netId: NetIdType,
|
||||||
|
relayers: CachedRelayerInfo[],
|
||||||
|
): Promise<{
|
||||||
validRelayers: RelayerInfo[];
|
validRelayers: RelayerInfo[];
|
||||||
invalidRelayers: RelayerError[];
|
invalidRelayers: RelayerError[];
|
||||||
}> {
|
}> {
|
||||||
const invalidRelayers: RelayerError[] = [];
|
const invalidRelayers: RelayerError[] = [];
|
||||||
|
|
||||||
const validRelayers = (await Promise.all(relayers.map((relayer) => this.filterRelayer(relayer)))).filter(
|
const validRelayers = (await Promise.all(relayers.map((relayer) => this.filterRelayer(netId, relayer)))).filter(
|
||||||
(r) => {
|
(r) => {
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Config, NetId, NetIdType } from '../networkConfig';
|
import { Config } from '../networkConfig';
|
||||||
import { addressSchemaType, bnSchemaType } from '.';
|
import { addressSchemaType, bnSchemaType } from '.';
|
||||||
|
|
||||||
export interface statusInstanceType {
|
export interface statusInstanceType {
|
||||||
@@ -10,7 +10,8 @@ export interface statusInstanceType {
|
|||||||
required: string[];
|
required: string[];
|
||||||
};
|
};
|
||||||
tokenAddress?: typeof addressSchemaType;
|
tokenAddress?: typeof addressSchemaType;
|
||||||
symbol?: { enum: string[] };
|
//symbol?: { enum: string[] };
|
||||||
|
symbol?: { type: string };
|
||||||
decimals: { enum: number[] };
|
decimals: { enum: number[] };
|
||||||
};
|
};
|
||||||
required: string[];
|
required: string[];
|
||||||
@@ -127,15 +128,23 @@ const statusSchema: statusSchema = {
|
|||||||
required: ['rewardAccount', 'instances', 'netId', 'tornadoServiceFee', 'version', 'health', 'currentQueue'],
|
required: ['rewardAccount', 'instances', 'netId', 'tornadoServiceFee', 'version', 'health', 'currentQueue'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getStatusSchema(netId: NetIdType, config: Config, tovarish: boolean) {
|
export function getStatusSchema(config: Config, tovarish: boolean) {
|
||||||
const { tokens, optionalTokens, disabledTokens, nativeCurrency } = config;
|
const { tokens, nativeCurrency } = config;
|
||||||
|
|
||||||
// deep copy schema
|
// deep copy schema
|
||||||
const schema = JSON.parse(JSON.stringify(statusSchema)) as statusSchema;
|
const schema = JSON.parse(JSON.stringify(statusSchema)) as statusSchema;
|
||||||
|
|
||||||
const instances = Object.keys(tokens).reduce(
|
const instances = Object.keys(tokens).reduce(
|
||||||
(acc: statusInstancesType, token) => {
|
(acc: statusInstancesType, token) => {
|
||||||
const { instanceAddress, tokenAddress, symbol, decimals, optionalInstances = [] } = tokens[token];
|
const {
|
||||||
|
isOptional,
|
||||||
|
isDisabled,
|
||||||
|
instanceAddress,
|
||||||
|
tokenAddress,
|
||||||
|
symbol,
|
||||||
|
decimals,
|
||||||
|
optionalInstances = [],
|
||||||
|
} = tokens[token];
|
||||||
const amounts = Object.keys(instanceAddress);
|
const amounts = Object.keys(instanceAddress);
|
||||||
|
|
||||||
const instanceProperties: statusInstanceType = {
|
const instanceProperties: statusInstanceType = {
|
||||||
@@ -160,12 +169,14 @@ export function getStatusSchema(netId: NetIdType, config: Config, tovarish: bool
|
|||||||
if (tokenAddress) {
|
if (tokenAddress) {
|
||||||
instanceProperties.properties.tokenAddress = addressSchemaType;
|
instanceProperties.properties.tokenAddress = addressSchemaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (symbol) {
|
if (symbol) {
|
||||||
instanceProperties.properties.symbol = { enum: [symbol] };
|
// instanceProperties.properties.symbol = { enum: [symbol] };
|
||||||
|
instanceProperties.properties.symbol = { type: 'string' };
|
||||||
}
|
}
|
||||||
|
|
||||||
acc.properties[token] = instanceProperties;
|
acc.properties[token] = instanceProperties;
|
||||||
if (!optionalTokens?.includes(token) && !disabledTokens?.includes(token)) {
|
if (!isOptional && !isDisabled) {
|
||||||
acc.required.push(token);
|
acc.required.push(token);
|
||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
@@ -179,13 +190,7 @@ export function getStatusSchema(netId: NetIdType, config: Config, tovarish: bool
|
|||||||
|
|
||||||
schema.properties.instances = instances;
|
schema.properties.instances = instances;
|
||||||
|
|
||||||
const _tokens = Object.keys(tokens).filter(
|
const _tokens = instances.required.filter((t) => t !== nativeCurrency);
|
||||||
(t) => t !== nativeCurrency && !config.optionalTokens?.includes(t) && !config.disabledTokens?.includes(t),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (netId === NetId.MAINNET) {
|
|
||||||
_tokens.push('torn');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_tokens.length) {
|
if (_tokens.length) {
|
||||||
const ethPrices: statusEthPricesType = {
|
const ethPrices: statusEthPricesType = {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
import { fetchData } from './providers';
|
import { fetchData } from './providers';
|
||||||
import { CachedRelayerInfo, MinimalEvents } from './events';
|
import { CachedRelayerInfo, MinimalEvents } from './events';
|
||||||
import { ajv, getEventsSchemaValidator, getStatusSchema } from './schemas';
|
import { ajv, getEventsSchemaValidator, getStatusSchema } from './schemas';
|
||||||
import { enabledChains, getConfig, NetId, NetIdType } from './networkConfig';
|
import { NetId, NetIdType } from './networkConfig';
|
||||||
|
|
||||||
// Return no more than 5K events per query
|
// Return no more than 5K events per query
|
||||||
export const MAX_TOVARISH_EVENTS = 5000;
|
export const MAX_TOVARISH_EVENTS = 5000;
|
||||||
@@ -76,9 +76,11 @@ export class TovarishClient extends RelayerClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async askRelayerStatus({
|
async askRelayerStatus({
|
||||||
|
netId,
|
||||||
hostname,
|
hostname,
|
||||||
url,
|
url,
|
||||||
}: {
|
}: {
|
||||||
|
netId: NetIdType;
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
// optional url if entered manually
|
// optional url if entered manually
|
||||||
url?: string;
|
url?: string;
|
||||||
@@ -86,6 +88,7 @@ export class TovarishClient extends RelayerClient {
|
|||||||
relayerAddress?: string;
|
relayerAddress?: string;
|
||||||
}): Promise<TovarishStatus> {
|
}): Promise<TovarishStatus> {
|
||||||
const status = (await super.askRelayerStatus({
|
const status = (await super.askRelayerStatus({
|
||||||
|
netId,
|
||||||
hostname,
|
hostname,
|
||||||
url,
|
url,
|
||||||
})) as TovarishStatus;
|
})) as TovarishStatus;
|
||||||
@@ -136,9 +139,9 @@ export class TovarishClient extends RelayerClient {
|
|||||||
|
|
||||||
for (const rawStatus of statusArray) {
|
for (const rawStatus of statusArray) {
|
||||||
const netId = rawStatus?.netId as NetIdType;
|
const netId = rawStatus?.netId as NetIdType;
|
||||||
const config = getConfig(netId);
|
const config = this.tornadoConfig.getConfig(netId);
|
||||||
|
|
||||||
const statusValidator = ajv.compile(getStatusSchema(rawStatus?.netId, config, this.tovarish));
|
const statusValidator = ajv.compile(getStatusSchema(config, this.tovarish));
|
||||||
|
|
||||||
if (!statusValidator(rawStatus)) {
|
if (!statusValidator(rawStatus)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -153,7 +156,7 @@ export class TovarishClient extends RelayerClient {
|
|||||||
throw new Error('Withdrawal queue is overloaded');
|
throw new Error('Withdrawal queue is overloaded');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enabledChains.includes(status.netId)) {
|
if (!this.tornadoConfig.chains.includes(status.netId)) {
|
||||||
throw new Error('This relayer serves a different network');
|
throw new Error('This relayer serves a different network');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,17 +174,21 @@ export class TovarishClient extends RelayerClient {
|
|||||||
return tovarishStatus;
|
return tovarishStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
async filterRelayer(relayer: CachedRelayerInfo): Promise<TovarishInfo | RelayerError | undefined> {
|
async filterRelayer(
|
||||||
|
netId: NetIdType,
|
||||||
|
relayer: CachedRelayerInfo,
|
||||||
|
): Promise<TovarishInfo | RelayerError | undefined> {
|
||||||
const { ensName, relayerAddress, tovarishHost, tovarishNetworks } = relayer;
|
const { ensName, relayerAddress, tovarishHost, tovarishNetworks } = relayer;
|
||||||
|
|
||||||
if (!tovarishHost || !tovarishNetworks?.includes(this.netId)) {
|
if (!tovarishHost || !tovarishNetworks?.includes(netId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hostname = `${tovarishHost}/${this.netId}`;
|
const hostname = `${tovarishHost}/${netId}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const status = await this.askRelayerStatus({
|
const status = await this.askRelayerStatus({
|
||||||
|
netId,
|
||||||
hostname,
|
hostname,
|
||||||
relayerAddress,
|
relayerAddress,
|
||||||
});
|
});
|
||||||
@@ -218,13 +225,16 @@ export class TovarishClient extends RelayerClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getValidRelayers(relayers: CachedRelayerInfo[]): Promise<{
|
async getValidRelayers(
|
||||||
|
netId: NetIdType,
|
||||||
|
relayers: CachedRelayerInfo[],
|
||||||
|
): Promise<{
|
||||||
validRelayers: TovarishInfo[];
|
validRelayers: TovarishInfo[];
|
||||||
invalidRelayers: RelayerError[];
|
invalidRelayers: RelayerError[];
|
||||||
}> {
|
}> {
|
||||||
const invalidRelayers: RelayerError[] = [];
|
const invalidRelayers: RelayerError[] = [];
|
||||||
|
|
||||||
const validRelayers = (await Promise.all(relayers.map((relayer) => this.filterRelayer(relayer)))).filter(
|
const validRelayers = (await Promise.all(relayers.map((relayer) => this.filterRelayer(netId, relayer)))).filter(
|
||||||
(r) => {
|
(r) => {
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user