forked from tornado-packages/tornado-core
Compare commits
5 Commits
84b6ed368e
...
700426acb7
Author | SHA1 | Date | |
---|---|---|---|
700426acb7 | |||
ef56beb29b | |||
e506c373de | |||
3df238e55f | |||
95dbf208c3 |
59
dist/events/base.d.ts
vendored
59
dist/events/base.d.ts
vendored
@ -1,9 +1,10 @@
|
||||
import { BaseContract, Provider, EventLog, ContractEventName } from 'ethers';
|
||||
import type { Tornado, TornadoRouter, TornadoProxyLight, Governance, RelayerRegistry, Echoer } from '@tornado/contracts';
|
||||
import type { Tornado, TornadoRouter, TornadoProxyLight, Governance, RelayerRegistry, Echoer, Aggregator } from '@tornado/contracts';
|
||||
import { BatchEventsService, BatchBlockService, BatchTransactionService, BatchEventOnProgress, BatchBlockOnProgress } from '../batch';
|
||||
import { fetchDataOptions } from '../providers';
|
||||
import type { NetIdType } from '../networkConfig';
|
||||
import type { BaseEvents, MinimalEvents, DepositsEvents, WithdrawalsEvents, EncryptedNotesEvents, AllGovernanceEvents, RegistersEvents, EchoEvents } from './types';
|
||||
import type { fetchDataOptions } from '../providers';
|
||||
import type { NetIdType, SubdomainMap } from '../networkConfig';
|
||||
import { RelayerParams } from '../relayerClient';
|
||||
import type { BaseEvents, CachedEvents, MinimalEvents, DepositsEvents, WithdrawalsEvents, EncryptedNotesEvents, AllGovernanceEvents, RegistersEvents, EchoEvents } from './types';
|
||||
export declare const DEPOSIT = "deposit";
|
||||
export declare const WITHDRAWAL = "withdrawal";
|
||||
export type BaseEventsServiceConstructor = {
|
||||
@ -38,7 +39,6 @@ export declare class BaseEventsService<EventType extends MinimalEvents> {
|
||||
deployedBlock: number;
|
||||
batchEventsService: BatchEventsService;
|
||||
fetchDataOptions?: fetchDataOptions;
|
||||
saveEventsPromise?: Promise<void>;
|
||||
constructor({ netId, provider, graphApi, subgraphName, contract, type, deployedBlock, fetchDataOptions, }: BaseEventsServiceConstructor);
|
||||
getInstanceName(): string;
|
||||
getType(): string;
|
||||
@ -53,8 +53,11 @@ export declare class BaseEventsService<EventType extends MinimalEvents> {
|
||||
* Get saved or cached events
|
||||
*/
|
||||
getEventsFromDB(): Promise<BaseEvents<EventType>>;
|
||||
getEventsFromCache(): Promise<BaseEvents<EventType>>;
|
||||
getSavedEvents(): Promise<BaseEvents<EventType>>;
|
||||
/**
|
||||
* Events from remote cache (Either from local cache, CDN, or from IPFS)
|
||||
*/
|
||||
getEventsFromCache(): Promise<CachedEvents<EventType>>;
|
||||
getSavedEvents(): Promise<BaseEvents<EventType> | CachedEvents<EventType>>;
|
||||
/**
|
||||
* Get latest events
|
||||
*/
|
||||
@ -167,17 +170,38 @@ export declare class BaseGovernanceService extends BaseEventsService<AllGovernan
|
||||
fromBlock: number;
|
||||
}): Promise<BaseEvents<AllGovernanceEvents>>;
|
||||
}
|
||||
/**
|
||||
* Essential params:
|
||||
* ensName, relayerAddress, hostnames
|
||||
* Other data is for historic purpose from relayer registry
|
||||
*/
|
||||
export interface CachedRelayerInfo extends RelayerParams {
|
||||
isRegistered?: boolean;
|
||||
owner?: string;
|
||||
stakeBalance?: string;
|
||||
hostnames: SubdomainMap;
|
||||
}
|
||||
export interface CachedRelayers {
|
||||
timestamp: number;
|
||||
relayers: CachedRelayerInfo[];
|
||||
fromCache?: boolean;
|
||||
}
|
||||
export type BaseRegistryServiceConstructor = {
|
||||
netId: NetIdType;
|
||||
provider: Provider;
|
||||
graphApi?: string;
|
||||
subgraphName?: string;
|
||||
RelayerRegistry: RelayerRegistry;
|
||||
Aggregator: Aggregator;
|
||||
relayerEnsSubdomains: SubdomainMap;
|
||||
deployedBlock?: number;
|
||||
fetchDataOptions?: fetchDataOptions;
|
||||
};
|
||||
export declare class BaseRegistryService extends BaseEventsService<RegistersEvents> {
|
||||
constructor({ netId, provider, graphApi, subgraphName, RelayerRegistry, deployedBlock, fetchDataOptions, }: BaseRegistryServiceConstructor);
|
||||
Aggregator: Aggregator;
|
||||
relayerEnsSubdomains: SubdomainMap;
|
||||
updateInterval: number;
|
||||
constructor({ netId, provider, graphApi, subgraphName, RelayerRegistry, Aggregator, relayerEnsSubdomains, deployedBlock, fetchDataOptions, }: BaseRegistryServiceConstructor);
|
||||
getInstanceName(): string;
|
||||
getType(): string;
|
||||
getGraphMethod(): string;
|
||||
@ -188,5 +212,22 @@ export declare class BaseRegistryService extends BaseEventsService<RegistersEven
|
||||
logIndex: number;
|
||||
transactionHash: string;
|
||||
}[]>;
|
||||
fetchRelayers(): Promise<RegistersEvents[]>;
|
||||
/**
|
||||
* 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({ timestamp, relayers }: CachedRelayers): Promise<void>;
|
||||
/**
|
||||
* Get cached or latest relayer and save to local
|
||||
*/
|
||||
updateRelayers(): Promise<CachedRelayers>;
|
||||
}
|
||||
|
3
dist/events/types.d.ts
vendored
3
dist/events/types.d.ts
vendored
@ -3,6 +3,9 @@ export interface BaseEvents<T> {
|
||||
events: T[];
|
||||
lastBlock: number | null;
|
||||
}
|
||||
export interface CachedEvents<T> extends BaseEvents<T> {
|
||||
fromCache: boolean;
|
||||
}
|
||||
export interface BaseGraphEvents<T> {
|
||||
events: T[];
|
||||
lastSyncBlock: number;
|
||||
|
7064
dist/index.js
vendored
7064
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
7063
dist/index.mjs
vendored
7063
dist/index.mjs
vendored
File diff suppressed because it is too large
Load Diff
37387
dist/index.umd.js
vendored
37387
dist/index.umd.js
vendored
File diff suppressed because one or more lines are too long
17963
dist/merkleTreeWorker.js
vendored
17963
dist/merkleTreeWorker.js
vendored
File diff suppressed because it is too large
Load Diff
27224
dist/merkleTreeWorker.umd.js
vendored
27224
dist/merkleTreeWorker.umd.js
vendored
File diff suppressed because one or more lines are too long
8
dist/networkConfig.d.ts
vendored
8
dist/networkConfig.d.ts
vendored
@ -67,8 +67,6 @@ export type Config = {
|
||||
registryContract?: string;
|
||||
aggregatorContract?: string;
|
||||
reverseRecordsContract?: string;
|
||||
gasPriceOracleContract?: string;
|
||||
gasStationApi?: string;
|
||||
ovmGasPriceOracleContract?: string;
|
||||
tornadoSubgraph: string;
|
||||
registrySubgraph?: string;
|
||||
@ -89,8 +87,11 @@ export type Config = {
|
||||
export type networkConfig = {
|
||||
[key in NetIdType]: Config;
|
||||
};
|
||||
export type SubdomainMap = {
|
||||
[key in NetIdType]: string;
|
||||
};
|
||||
export declare const defaultConfig: networkConfig;
|
||||
export declare const enabledChains: number[];
|
||||
export declare const enabledChains: NetIdType[];
|
||||
/**
|
||||
* Custom config object to extend default config
|
||||
*
|
||||
@ -114,3 +115,4 @@ export declare function getInstanceByAddress({ netId, address }: {
|
||||
currency: string;
|
||||
} | undefined;
|
||||
export declare function getSubdomains(): string[];
|
||||
export declare function getRelayerEnsSubdomains(): SubdomainMap;
|
||||
|
8
dist/providers.d.ts
vendored
8
dist/providers.d.ts
vendored
@ -1,9 +1,6 @@
|
||||
/// <reference types="node" />
|
||||
/// <reference types="node" />
|
||||
/// <reference types="node" />
|
||||
import type { EventEmitter } from 'stream';
|
||||
import type { RequestOptions } from 'http';
|
||||
import { JsonRpcApiProvider, JsonRpcProvider, Wallet, FetchGetUrlFunc, Provider, SigningKey, TransactionRequest, JsonRpcSigner, BrowserProvider, Networkish, Eip1193Provider, VoidSigner, FetchUrlFeeDataNetworkPlugin } from 'ethers';
|
||||
import { JsonRpcApiProvider, JsonRpcProvider, Wallet, FetchGetUrlFunc, Provider, SigningKey, TransactionRequest, JsonRpcSigner, BrowserProvider, Networkish, Eip1193Provider, VoidSigner } from 'ethers';
|
||||
import type { RequestInfo, RequestInit, Response, HeadersInit } from 'node-fetch';
|
||||
import type { Config, NetIdType } from './networkConfig';
|
||||
declare global {
|
||||
@ -36,10 +33,7 @@ export declare function fetchData(url: string, options?: fetchDataOptions): Prom
|
||||
export declare const fetchGetUrlFunc: (options?: fetchDataOptions) => FetchGetUrlFunc;
|
||||
export type getProviderOptions = fetchDataOptions & {
|
||||
pollingInterval?: number;
|
||||
gasPriceOracle?: string;
|
||||
gasStationApi?: string;
|
||||
};
|
||||
export declare function getGasOraclePlugin(networkKey: string, fetchOptions?: getProviderOptions): FetchUrlFeeDataNetworkPlugin;
|
||||
export declare function getProvider(rpcUrl: string, fetchOptions?: getProviderOptions): Promise<JsonRpcProvider>;
|
||||
export declare function getProviderWithNetId(netId: NetIdType, rpcUrl: string, config: Config, fetchOptions?: getProviderOptions): JsonRpcProvider;
|
||||
export declare const populateTransaction: (signer: TornadoWallet | TornadoVoidSigner | TornadoRpcSigner, tx: TransactionRequest) => Promise<TransactionRequest>;
|
||||
|
33
dist/relayerClient.d.ts
vendored
33
dist/relayerClient.d.ts
vendored
@ -1,35 +1,36 @@
|
||||
import type { Aggregator } from '@tornado/contracts';
|
||||
import type { RelayerStructOutput } from '@tornado/contracts/dist/contracts/Governance/Aggregator/Aggregator';
|
||||
import { NetIdType, Config } from './networkConfig';
|
||||
import { fetchDataOptions } from './providers';
|
||||
import type { snarkProofs } from './websnark';
|
||||
import { CachedRelayerInfo } from './events/base';
|
||||
export declare const MIN_FEE = 0.1;
|
||||
export declare const MAX_FEE = 0.6;
|
||||
export declare const MIN_STAKE_BALANCE: bigint;
|
||||
export interface RelayerParams {
|
||||
ensName: string;
|
||||
relayerAddress?: string;
|
||||
relayerAddress: string;
|
||||
}
|
||||
export interface Relayer {
|
||||
/**
|
||||
* Info from relayer status
|
||||
*/
|
||||
export type RelayerInfo = RelayerParams & {
|
||||
netId: NetIdType;
|
||||
url: string;
|
||||
hostname: string;
|
||||
rewardAccount: string;
|
||||
instances: string[];
|
||||
stakeBalance?: string;
|
||||
gasPrice?: number;
|
||||
ethPrices?: {
|
||||
[key in string]: string;
|
||||
};
|
||||
currentQueue: number;
|
||||
tornadoServiceFee: number;
|
||||
}
|
||||
export type RelayerInfo = Relayer & {
|
||||
ensName: string;
|
||||
stakeBalance: bigint;
|
||||
relayerAddress: string;
|
||||
};
|
||||
export type RelayerError = {
|
||||
hostname: string;
|
||||
relayerAddress?: string;
|
||||
errorMessage?: string;
|
||||
hasError: boolean;
|
||||
};
|
||||
export interface RelayerStatus {
|
||||
url: string;
|
||||
@ -87,7 +88,7 @@ export interface semanticVersion {
|
||||
}
|
||||
export declare function parseSemanticVersion(version: string): semanticVersion;
|
||||
export declare function isRelayerUpdated(relayerVersion: string, netId: NetIdType): boolean;
|
||||
export declare function calculateScore({ stakeBalance, tornadoServiceFee }: RelayerInfo, minFee?: number, maxFee?: number): bigint;
|
||||
export declare function calculateScore({ stakeBalance, tornadoServiceFee }: RelayerInfo): bigint;
|
||||
export declare function getWeightRandom(weightsScores: bigint[], random: bigint): number;
|
||||
export type RelayerInstanceList = {
|
||||
[key in string]: {
|
||||
@ -97,11 +98,10 @@ export type RelayerInstanceList = {
|
||||
};
|
||||
};
|
||||
export declare function getSupportedInstances(instanceList: RelayerInstanceList): string[];
|
||||
export declare function pickWeightedRandomRelayer(relayers: RelayerInfo[], netId: NetIdType): RelayerInfo;
|
||||
export declare function pickWeightedRandomRelayer(relayers: RelayerInfo[]): RelayerInfo;
|
||||
export interface RelayerClientConstructor {
|
||||
netId: NetIdType;
|
||||
config: Config;
|
||||
Aggregator: Aggregator;
|
||||
fetchDataOptions?: fetchDataOptions;
|
||||
}
|
||||
export type RelayerClientWithdraw = snarkProofs & {
|
||||
@ -110,16 +110,15 @@ export type RelayerClientWithdraw = snarkProofs & {
|
||||
export declare class RelayerClient {
|
||||
netId: NetIdType;
|
||||
config: Config;
|
||||
Aggregator: Aggregator;
|
||||
selectedRelayer?: Relayer;
|
||||
selectedRelayer?: RelayerInfo;
|
||||
fetchDataOptions?: fetchDataOptions;
|
||||
constructor({ netId, config, Aggregator, fetchDataOptions }: RelayerClientConstructor);
|
||||
constructor({ netId, config, fetchDataOptions }: RelayerClientConstructor);
|
||||
askRelayerStatus({ hostname, relayerAddress, }: {
|
||||
hostname: string;
|
||||
relayerAddress?: string;
|
||||
}): Promise<RelayerStatus>;
|
||||
filterRelayer(curr: RelayerStructOutput, relayer: RelayerParams, subdomains: string[], debugRelayer?: boolean): Promise<RelayerInfo | RelayerError>;
|
||||
getValidRelayers(relayers: RelayerParams[], subdomains: string[], debugRelayer?: boolean): Promise<{
|
||||
filterRelayer(relayer: CachedRelayerInfo): Promise<RelayerInfo | RelayerError | undefined>;
|
||||
getValidRelayers(relayers: CachedRelayerInfo[]): Promise<{
|
||||
validRelayers: RelayerInfo[];
|
||||
invalidRelayers: RelayerError[];
|
||||
}>;
|
||||
|
1
dist/typechain/factories/index.d.ts
vendored
1
dist/typechain/factories/index.d.ts
vendored
@ -1,6 +1,5 @@
|
||||
export { ENS__factory } from "./ENS__factory";
|
||||
export { ERC20__factory } from "./ERC20__factory";
|
||||
export { GasPriceOracle__factory } from "./GasPriceOracle__factory";
|
||||
export { Multicall__factory } from "./Multicall__factory";
|
||||
export { OffchainOracle__factory } from "./OffchainOracle__factory";
|
||||
export { OvmGasPriceOracle__factory } from "./OvmGasPriceOracle__factory";
|
||||
|
2
dist/typechain/index.d.ts
vendored
2
dist/typechain/index.d.ts
vendored
@ -1,6 +1,5 @@
|
||||
export type { ENS } from "./ENS";
|
||||
export type { ERC20 } from "./ERC20";
|
||||
export type { GasPriceOracle } from "./GasPriceOracle";
|
||||
export type { Multicall } from "./Multicall";
|
||||
export type { OffchainOracle } from "./OffchainOracle";
|
||||
export type { OvmGasPriceOracle } from "./OvmGasPriceOracle";
|
||||
@ -8,7 +7,6 @@ export type { ReverseRecords } from "./ReverseRecords";
|
||||
export * as factories from "./factories";
|
||||
export { ENS__factory } from "./factories/ENS__factory";
|
||||
export { ERC20__factory } from "./factories/ERC20__factory";
|
||||
export { GasPriceOracle__factory } from "./factories/GasPriceOracle__factory";
|
||||
export { Multicall__factory } from "./factories/Multicall__factory";
|
||||
export { OffchainOracle__factory } from "./factories/OffchainOracle__factory";
|
||||
export { OvmGasPriceOracle__factory } from "./factories/OvmGasPriceOracle__factory";
|
||||
|
2
dist/utils.d.ts
vendored
2
dist/utils.d.ts
vendored
@ -1,5 +1,3 @@
|
||||
/// <reference types="node" />
|
||||
/// <reference types="node" />
|
||||
import { webcrypto } from 'crypto';
|
||||
import BN from 'bn.js';
|
||||
import type { BigNumberish } from 'ethers';
|
||||
|
40
package.json
40
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tornado/core",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.7",
|
||||
"description": "An SDK for building applications on top of Privacy Pools",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
@ -31,46 +31,44 @@
|
||||
"yarn.lock"
|
||||
],
|
||||
"dependencies": {
|
||||
"@metamask/eth-sig-util": "^7.0.1",
|
||||
"@metamask/eth-sig-util": "^7.0.3",
|
||||
"@tornado/contracts": "^1.0.0",
|
||||
"@tornado/fixed-merkle-tree": "^0.7.3",
|
||||
"@tornado/snarkjs": "^0.1.20",
|
||||
"@tornado/websnark": "^0.0.4",
|
||||
"ajv": "^8.12.0",
|
||||
"ajv": "^8.17.1",
|
||||
"bn.js": "^5.2.1",
|
||||
"circomlibjs": "0.1.7",
|
||||
"cross-fetch": "^4.0.0",
|
||||
"ethers": "^6.4.0",
|
||||
"ethers": "^6.13.2",
|
||||
"ffjavascript": "0.2.48",
|
||||
"fflate": "^0.8.2"
|
||||
},
|
||||
"optionalDependencies": {},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-commonjs": "^26.0.1",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@typechain/ethers-v6": "^0.5.1",
|
||||
"@types/bn.js": "^5.1.5",
|
||||
"@types/bn.js": "^5.1.6",
|
||||
"@types/circomlibjs": "^0.1.6",
|
||||
"@types/node": "^20.12.5",
|
||||
"@types/node": "^22.5.5",
|
||||
"@types/node-fetch": "^2.6.11",
|
||||
"@typescript-eslint/eslint-plugin": "^7.6.0",
|
||||
"@typescript-eslint/parser": "^7.6.0",
|
||||
"esbuild": "^0.20.2",
|
||||
"esbuild-loader": "^4.1.0",
|
||||
"eslint": "^8.57.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.6.0",
|
||||
"@typescript-eslint/parser": "^8.6.0",
|
||||
"esbuild-loader": "^4.2.2",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"node-polyfill-webpack-plugin": "^3.0.0",
|
||||
"prettier": "^3.2.5",
|
||||
"rollup": "^4.14.1",
|
||||
"eslint-import-resolver-typescript": "^3.6.3",
|
||||
"eslint-plugin-import": "^2.30.0",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"node-polyfill-webpack-plugin": "^4.0.0",
|
||||
"prettier": "^3.3.3",
|
||||
"rollup": "^4.22.0",
|
||||
"rollup-plugin-esbuild": "^6.1.1",
|
||||
"tsc": "^2.0.4",
|
||||
"typechain": "^8.3.2",
|
||||
"typescript": "^5.4.4",
|
||||
"webpack": "^5.91.0",
|
||||
"typescript": "^5.6.2",
|
||||
"webpack": "^5.94.0",
|
||||
"webpack-cli": "^5.1.4"
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import { readFileSync } from 'fs';
|
||||
const pkgJson = JSON.parse(readFileSync("./package.json"));
|
||||
|
||||
const external = Object.keys(pkgJson.dependencies).concat(
|
||||
Object.keys(pkgJson.optionalDependencies),
|
||||
Object.keys(pkgJson.optionalDependencies || {}),
|
||||
[
|
||||
'http-proxy-agent',
|
||||
'https-proxy-agent',
|
||||
|
@ -1,189 +0,0 @@
|
||||
[
|
||||
{
|
||||
"inputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "GAS_UNIT",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "_derivationThresold",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "changeDerivationThresold",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "_gasUnit",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "changeGasUnit",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "_heartbeat",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "changeHeartbeat",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "changeOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "derivationThresold",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "gasPrice",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "heartbeat",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "maxFeePerGas",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "maxPriorityFeePerGas",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "pastGasPrice",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "_gasPrice",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "setGasPrice",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "timestamp",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
@ -1,4 +1,15 @@
|
||||
import { BaseContract, Provider, EventLog, TransactionResponse, getAddress, Block, ContractEventName } from 'ethers';
|
||||
import {
|
||||
BaseContract,
|
||||
Provider,
|
||||
EventLog,
|
||||
TransactionResponse,
|
||||
getAddress,
|
||||
Block,
|
||||
ContractEventName,
|
||||
namehash,
|
||||
formatEther,
|
||||
} from 'ethers';
|
||||
|
||||
import type {
|
||||
Tornado,
|
||||
TornadoRouter,
|
||||
@ -6,8 +17,11 @@ import type {
|
||||
Governance,
|
||||
RelayerRegistry,
|
||||
Echoer,
|
||||
Aggregator,
|
||||
} from '@tornado/contracts';
|
||||
|
||||
import * as graph from '../graphql';
|
||||
|
||||
import {
|
||||
BatchEventsService,
|
||||
BatchBlockService,
|
||||
@ -15,10 +29,14 @@ import {
|
||||
BatchEventOnProgress,
|
||||
BatchBlockOnProgress,
|
||||
} from '../batch';
|
||||
import { fetchDataOptions } from '../providers';
|
||||
import type { NetIdType } from '../networkConfig';
|
||||
|
||||
import type { fetchDataOptions } from '../providers';
|
||||
import type { NetIdType, SubdomainMap } from '../networkConfig';
|
||||
import { RelayerParams, MIN_STAKE_BALANCE } from '../relayerClient';
|
||||
|
||||
import type {
|
||||
BaseEvents,
|
||||
CachedEvents,
|
||||
MinimalEvents,
|
||||
DepositsEvents,
|
||||
WithdrawalsEvents,
|
||||
@ -77,8 +95,6 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
||||
batchEventsService: BatchEventsService;
|
||||
fetchDataOptions?: fetchDataOptions;
|
||||
|
||||
saveEventsPromise?: Promise<void>;
|
||||
|
||||
constructor({
|
||||
netId,
|
||||
provider,
|
||||
@ -153,14 +169,18 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
||||
};
|
||||
}
|
||||
|
||||
async getEventsFromCache(): Promise<BaseEvents<EventType>> {
|
||||
/**
|
||||
* Events from remote cache (Either from local cache, CDN, or from IPFS)
|
||||
*/
|
||||
async getEventsFromCache(): Promise<CachedEvents<EventType>> {
|
||||
return {
|
||||
events: [],
|
||||
lastBlock: null,
|
||||
fromCache: true,
|
||||
};
|
||||
}
|
||||
|
||||
async getSavedEvents(): Promise<BaseEvents<EventType>> {
|
||||
async getSavedEvents(): Promise<BaseEvents<EventType> | CachedEvents<EventType>> {
|
||||
let cachedEvents = await this.getEventsFromDB();
|
||||
|
||||
if (!cachedEvents || !cachedEvents.events.length) {
|
||||
@ -317,7 +337,10 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
||||
|
||||
this.validateEvents({ events: allEvents, lastBlock });
|
||||
|
||||
this.saveEventsPromise = this.saveEvents({ events: allEvents, lastBlock });
|
||||
// If the events are loaded from cache or we have found new events, save them
|
||||
if ((savedEvents as CachedEvents<EventType>).fromCache || newEvents.events.length) {
|
||||
await this.saveEvents({ events: allEvents, lastBlock });
|
||||
}
|
||||
|
||||
return {
|
||||
events: allEvents,
|
||||
@ -735,27 +758,58 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Essential params:
|
||||
* ensName, relayerAddress, hostnames
|
||||
* Other data is for historic purpose from relayer registry
|
||||
*/
|
||||
export interface CachedRelayerInfo extends RelayerParams {
|
||||
isRegistered?: boolean;
|
||||
owner?: string;
|
||||
stakeBalance?: string;
|
||||
hostnames: SubdomainMap;
|
||||
}
|
||||
|
||||
export interface CachedRelayers {
|
||||
timestamp: number;
|
||||
relayers: CachedRelayerInfo[];
|
||||
fromCache?: boolean;
|
||||
}
|
||||
|
||||
export type BaseRegistryServiceConstructor = {
|
||||
netId: NetIdType;
|
||||
provider: Provider;
|
||||
graphApi?: string;
|
||||
subgraphName?: string;
|
||||
RelayerRegistry: RelayerRegistry;
|
||||
Aggregator: Aggregator;
|
||||
relayerEnsSubdomains: SubdomainMap;
|
||||
deployedBlock?: number;
|
||||
fetchDataOptions?: fetchDataOptions;
|
||||
};
|
||||
|
||||
export class BaseRegistryService extends BaseEventsService<RegistersEvents> {
|
||||
Aggregator: Aggregator;
|
||||
relayerEnsSubdomains: SubdomainMap;
|
||||
updateInterval: number;
|
||||
|
||||
constructor({
|
||||
netId,
|
||||
provider,
|
||||
graphApi,
|
||||
subgraphName,
|
||||
RelayerRegistry,
|
||||
Aggregator,
|
||||
relayerEnsSubdomains,
|
||||
deployedBlock,
|
||||
fetchDataOptions,
|
||||
}: BaseRegistryServiceConstructor) {
|
||||
super({ netId, provider, graphApi, subgraphName, contract: RelayerRegistry, deployedBlock, fetchDataOptions });
|
||||
|
||||
this.Aggregator = Aggregator;
|
||||
this.relayerEnsSubdomains = relayerEnsSubdomains;
|
||||
|
||||
this.updateInterval = 86400;
|
||||
}
|
||||
|
||||
getInstanceName() {
|
||||
@ -788,7 +842,122 @@ export class BaseRegistryService extends BaseEventsService<RegistersEvents> {
|
||||
});
|
||||
}
|
||||
|
||||
async fetchRelayers(): Promise<RegistersEvents[]> {
|
||||
return (await this.updateEvents()).events;
|
||||
/**
|
||||
* Get saved or cached relayers
|
||||
*/
|
||||
async getRelayersFromDB(): Promise<CachedRelayers> {
|
||||
return {
|
||||
timestamp: 0,
|
||||
relayers: [],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Relayers from remote cache (Either from local cache, CDN, or from IPFS)
|
||||
*/
|
||||
async getRelayersFromCache(): Promise<CachedRelayers> {
|
||||
return {
|
||||
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 registerEvents = (await this.updateEvents()).events;
|
||||
|
||||
const subdomains = Object.values(this.relayerEnsSubdomains);
|
||||
|
||||
const registerSet = new Set();
|
||||
|
||||
const uniqueRegisters = registerEvents.reverse().filter(({ ensName }) => {
|
||||
if (!registerSet.has(ensName)) {
|
||||
registerSet.add(ensName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const relayerNameHashes = uniqueRegisters.map((r) => namehash(r.ensName));
|
||||
|
||||
const [relayersData, timestamp] = await Promise.all([
|
||||
this.Aggregator.relayersData.staticCall(relayerNameHashes, subdomains),
|
||||
this.provider.getBlock('latest').then((b) => Number(b?.timestamp)),
|
||||
]);
|
||||
|
||||
const relayers = relayersData
|
||||
.map(({ owner, balance: stakeBalance, records, isRegistered }, index) => {
|
||||
const { ensName, relayerAddress } = uniqueRegisters[index];
|
||||
|
||||
const hostnames = {} as SubdomainMap;
|
||||
|
||||
records.forEach((record, recordIndex) => {
|
||||
if (record) {
|
||||
hostnames[Number(Object.keys(this.relayerEnsSubdomains)[recordIndex])] = record;
|
||||
}
|
||||
});
|
||||
|
||||
const isOwner = !relayerAddress || relayerAddress === owner;
|
||||
const hasMinBalance = stakeBalance >= MIN_STAKE_BALANCE;
|
||||
|
||||
const preCondition = Object.keys(hostnames).length && isOwner && isRegistered && hasMinBalance;
|
||||
|
||||
if (preCondition) {
|
||||
return {
|
||||
ensName,
|
||||
relayerAddress,
|
||||
isRegistered,
|
||||
owner,
|
||||
stakeBalance: formatEther(stakeBalance),
|
||||
hostnames,
|
||||
} as CachedRelayerInfo;
|
||||
}
|
||||
})
|
||||
.filter((r) => r) as CachedRelayerInfo[];
|
||||
|
||||
return {
|
||||
timestamp,
|
||||
relayers,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle saving relayers
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async saveRelayers({ timestamp, relayers }: CachedRelayers) {}
|
||||
|
||||
/**
|
||||
* Get cached or latest relayer and save to local
|
||||
*/
|
||||
async updateRelayers(): Promise<CachedRelayers> {
|
||||
// eslint-disable-next-line prefer-const
|
||||
let { 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');
|
||||
|
||||
({ timestamp, relayers } = await this.getLatestRelayers());
|
||||
|
||||
shouldSave = true;
|
||||
}
|
||||
|
||||
if (shouldSave) {
|
||||
await this.saveRelayers({ timestamp, relayers });
|
||||
}
|
||||
|
||||
return { timestamp, relayers };
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,10 @@ export interface BaseEvents<T> {
|
||||
lastBlock: number | null;
|
||||
}
|
||||
|
||||
export interface CachedEvents<T> extends BaseEvents<T> {
|
||||
fromCache: boolean;
|
||||
}
|
||||
|
||||
export interface BaseGraphEvents<T> {
|
||||
events: T[];
|
||||
lastSyncBlock: number;
|
||||
|
@ -78,8 +78,6 @@ export type Config = {
|
||||
registryContract?: string;
|
||||
aggregatorContract?: string;
|
||||
reverseRecordsContract?: string;
|
||||
gasPriceOracleContract?: string;
|
||||
gasStationApi?: string;
|
||||
ovmGasPriceOracleContract?: string;
|
||||
tornadoSubgraph: string;
|
||||
registrySubgraph?: string;
|
||||
@ -104,13 +102,8 @@ export type networkConfig = {
|
||||
[key in NetIdType]: Config;
|
||||
};
|
||||
|
||||
const theGraph = {
|
||||
name: 'Hosted Graph',
|
||||
url: 'https://api.thegraph.com',
|
||||
};
|
||||
const tornado = {
|
||||
name: 'Tornado Subgraphs',
|
||||
url: 'https://tornadocash-rpc.com',
|
||||
export type SubdomainMap = {
|
||||
[key in NetIdType]: string;
|
||||
};
|
||||
|
||||
export const defaultConfig: networkConfig = {
|
||||
@ -130,14 +123,26 @@ export const defaultConfig: networkConfig = {
|
||||
networkName: 'Ethereum Mainnet',
|
||||
deployedBlock: 9116966,
|
||||
rpcUrls: {
|
||||
tornadoRPC: {
|
||||
name: 'Tornado RPC',
|
||||
url: 'https://tornadocash-rpc.com/mainnet',
|
||||
},
|
||||
mevblockerRPC: {
|
||||
name: 'MevblockerRPC',
|
||||
url: 'https://rpc.mevblocker.io',
|
||||
},
|
||||
keydonix: {
|
||||
name: 'keydonix',
|
||||
url: 'https://ethereum.keydonix.com/v1/mainnet',
|
||||
},
|
||||
SecureRpc: {
|
||||
name: 'SecureRpc',
|
||||
url: 'https://api.securerpc.com/v1',
|
||||
},
|
||||
meowrpc: {
|
||||
name: 'Meow RPC',
|
||||
url: 'https://eth.meowrpc.com',
|
||||
},
|
||||
stackup: {
|
||||
name: 'Stackup RPC',
|
||||
url: 'https://public.stackup.sh/api/v1/node/ethereum-mainnet',
|
||||
},
|
||||
oneRPC: {
|
||||
name: '1RPC',
|
||||
url: 'https://1rpc.io/eth',
|
||||
@ -156,10 +161,7 @@ export const defaultConfig: networkConfig = {
|
||||
tornadoSubgraph: 'tornadocash/mainnet-tornado-subgraph',
|
||||
registrySubgraph: 'tornadocash/tornado-relayer-registry',
|
||||
governanceSubgraph: 'tornadocash/tornado-governance',
|
||||
subgraphs: {
|
||||
tornado,
|
||||
theGraph,
|
||||
},
|
||||
subgraphs: {},
|
||||
tokens: {
|
||||
eth: {
|
||||
instanceAddress: {
|
||||
@ -262,14 +264,27 @@ export const defaultConfig: networkConfig = {
|
||||
echoContract: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
||||
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||
tornadoSubgraph: 'tornadocash/bsc-tornado-subgraph',
|
||||
subgraphs: {
|
||||
tornado,
|
||||
theGraph,
|
||||
},
|
||||
subgraphs: {},
|
||||
rpcUrls: {
|
||||
tornadoRPC: {
|
||||
name: 'Tornado RPC',
|
||||
url: 'https://tornadocash-rpc.com/bsc',
|
||||
bnbchain: {
|
||||
name: 'BNB Chain',
|
||||
url: 'https://bsc-dataseed.bnbchain.org',
|
||||
},
|
||||
ninicoin: {
|
||||
name: 'ninicoin',
|
||||
url: 'https://bsc-dataseed1.ninicoin.io',
|
||||
},
|
||||
nodereal: {
|
||||
name: 'NodeReal',
|
||||
url: 'https://binance.nodereal.io',
|
||||
},
|
||||
meowrpc: {
|
||||
name: 'Meow RPC',
|
||||
url: 'https://bsc.meowrpc.com',
|
||||
},
|
||||
stackup: {
|
||||
name: 'Stackup RPC',
|
||||
url: 'https://public.stackup.sh/api/v1/node/bsc-mainnet',
|
||||
},
|
||||
oneRPC: {
|
||||
name: '1RPC',
|
||||
@ -314,17 +329,21 @@ export const defaultConfig: networkConfig = {
|
||||
routerContract: '0x0D5550d52428E7e3175bfc9550207e4ad3859b17',
|
||||
echoContract: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
||||
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||
gasPriceOracleContract: '0xF81A8D8D3581985D3969fe53bFA67074aDFa8F3C',
|
||||
tornadoSubgraph: 'tornadocash/matic-tornado-subgraph',
|
||||
subgraphs: {
|
||||
tornado,
|
||||
theGraph,
|
||||
},
|
||||
subgraphs: {},
|
||||
rpcUrls: {
|
||||
oneRpc: {
|
||||
name: '1RPC',
|
||||
url: 'https://1rpc.io/matic',
|
||||
},
|
||||
meowrpc: {
|
||||
name: 'Meow RPC',
|
||||
url: 'https://polygon.meowrpc.com',
|
||||
},
|
||||
stackup: {
|
||||
name: 'Stackup RPC',
|
||||
url: 'https://public.stackup.sh/api/v1/node/polygon-mainnet',
|
||||
},
|
||||
},
|
||||
tokens: {
|
||||
matic: {
|
||||
@ -366,14 +385,19 @@ export const defaultConfig: networkConfig = {
|
||||
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||
ovmGasPriceOracleContract: '0x420000000000000000000000000000000000000F',
|
||||
tornadoSubgraph: 'tornadocash/optimism-tornado-subgraph',
|
||||
subgraphs: {
|
||||
tornado,
|
||||
theGraph,
|
||||
},
|
||||
subgraphs: {},
|
||||
rpcUrls: {
|
||||
tornadoRPC: {
|
||||
name: 'Tornado RPC',
|
||||
url: 'https://tornadocash-rpc.com/op',
|
||||
optimism: {
|
||||
name: 'Optimism',
|
||||
url: 'https://mainnet.optimism.io',
|
||||
},
|
||||
meowrpc: {
|
||||
name: 'Meow RPC',
|
||||
url: 'https://optimism.meowrpc.com',
|
||||
},
|
||||
stackup: {
|
||||
name: 'Stackup RPC',
|
||||
url: 'https://public.stackup.sh/api/v1/node/optimism-mainnet',
|
||||
},
|
||||
oneRpc: {
|
||||
name: '1RPC',
|
||||
@ -419,19 +443,24 @@ export const defaultConfig: networkConfig = {
|
||||
echoContract: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
||||
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||
tornadoSubgraph: 'tornadocash/arbitrum-tornado-subgraph',
|
||||
subgraphs: {
|
||||
tornado,
|
||||
theGraph,
|
||||
},
|
||||
subgraphs: {},
|
||||
rpcUrls: {
|
||||
oneRpc: {
|
||||
name: '1rpc',
|
||||
url: 'https://1rpc.io/arb',
|
||||
},
|
||||
Arbitrum: {
|
||||
name: 'Arbitrum RPC',
|
||||
url: 'https://arb1.arbitrum.io/rpc',
|
||||
},
|
||||
meowrpc: {
|
||||
name: 'Meow RPC',
|
||||
url: 'https://arbitrum.meowrpc.com',
|
||||
},
|
||||
stackup: {
|
||||
name: 'Stackup RPC',
|
||||
url: 'https://public.stackup.sh/api/v1/node/arbitrum-one',
|
||||
},
|
||||
oneRpc: {
|
||||
name: '1rpc',
|
||||
url: 'https://1rpc.io/arb',
|
||||
},
|
||||
},
|
||||
tokens: {
|
||||
eth: {
|
||||
@ -472,19 +501,20 @@ export const defaultConfig: networkConfig = {
|
||||
echoContract: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
||||
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||
tornadoSubgraph: 'tornadocash/xdai-tornado-subgraph',
|
||||
subgraphs: {
|
||||
tornado,
|
||||
theGraph,
|
||||
},
|
||||
subgraphs: {},
|
||||
rpcUrls: {
|
||||
tornadoRPC: {
|
||||
name: 'Tornado RPC',
|
||||
url: 'https://tornadocash-rpc.com/gnosis',
|
||||
gnosis: {
|
||||
name: 'Gnosis',
|
||||
url: 'https://rpc.gnosischain.com',
|
||||
},
|
||||
blockPi: {
|
||||
name: 'BlockPi',
|
||||
url: 'https://gnosis.blockpi.network/v1/rpc/public',
|
||||
},
|
||||
oneRpc: {
|
||||
name: '1rpc',
|
||||
url: 'https://1rpc.io/gnosis',
|
||||
},
|
||||
},
|
||||
tokens: {
|
||||
xdai: {
|
||||
@ -525,9 +555,7 @@ export const defaultConfig: networkConfig = {
|
||||
echoContract: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
||||
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||
tornadoSubgraph: 'tornadocash/avalanche-tornado-subgraph',
|
||||
subgraphs: {
|
||||
theGraph,
|
||||
},
|
||||
subgraphs: {},
|
||||
rpcUrls: {
|
||||
publicRpc: {
|
||||
name: 'Avalanche RPC',
|
||||
@ -585,18 +613,24 @@ export const defaultConfig: networkConfig = {
|
||||
aggregatorContract: '0x4088712AC9fad39ea133cdb9130E465d235e9642',
|
||||
reverseRecordsContract: '0xEc29700C0283e5Be64AcdFe8077d6cC95dE23C23',
|
||||
tornadoSubgraph: 'tornadocash/sepolia-tornado-subgraph',
|
||||
subgraphs: {
|
||||
tornado,
|
||||
},
|
||||
subgraphs: {},
|
||||
rpcUrls: {
|
||||
tornadoRPC: {
|
||||
name: 'Tornado RPC',
|
||||
url: 'https://tornadocash-rpc.com/sepolia',
|
||||
},
|
||||
sepolia: {
|
||||
name: 'Sepolia RPC',
|
||||
url: 'https://rpc.sepolia.org',
|
||||
},
|
||||
stackup: {
|
||||
name: 'Stackup',
|
||||
url: 'https://public.stackup.sh/api/v1/node/ethereum-sepolia',
|
||||
},
|
||||
onerpc: {
|
||||
name: '1rpc',
|
||||
url: 'https://1rpc.io/sepolia',
|
||||
},
|
||||
ethpandaops: {
|
||||
name: 'ethpandaops',
|
||||
url: 'https://rpc.sepolia.ethpandaops.io',
|
||||
},
|
||||
},
|
||||
tokens: {
|
||||
eth: {
|
||||
@ -708,3 +742,12 @@ export function getSubdomains() {
|
||||
|
||||
return enabledChains.map((chain) => allConfig[chain].relayerEnsSubdomain);
|
||||
}
|
||||
|
||||
export function getRelayerEnsSubdomains() {
|
||||
const allConfig = getNetworkConfig();
|
||||
|
||||
return Object.keys(allConfig).reduce((acc, chain) => {
|
||||
acc[Number(chain)] = allConfig[Number(chain)].relayerEnsSubdomain;
|
||||
return acc;
|
||||
}, {} as SubdomainMap);
|
||||
}
|
||||
|
132
src/providers.ts
132
src/providers.ts
@ -17,17 +17,15 @@ import {
|
||||
Eip1193Provider,
|
||||
VoidSigner,
|
||||
Network,
|
||||
parseUnits,
|
||||
FetchUrlFeeDataNetworkPlugin,
|
||||
FeeData,
|
||||
EnsPlugin,
|
||||
GasCostPlugin,
|
||||
} from 'ethers';
|
||||
import type { RequestInfo, RequestInit, Response, HeadersInit } from 'node-fetch';
|
||||
import { GasPriceOracle, GasPriceOracle__factory, Multicall, Multicall__factory } from './typechain';
|
||||
// Temporary workaround until @types/node-fetch is compatible with @types/node
|
||||
import type { AbortSignal as FetchAbortSignal } from 'node-fetch/externals';
|
||||
import { isNode, sleep } from './utils';
|
||||
import type { Config, NetIdType } from './networkConfig';
|
||||
import { multicall } from './multicall';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@ -51,7 +49,7 @@ export type fetchDataOptions = RequestInit & {
|
||||
timeout?: number;
|
||||
proxy?: string;
|
||||
torPort?: number;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
debug?: Function;
|
||||
returnResponse?: boolean;
|
||||
};
|
||||
@ -69,11 +67,11 @@ export function getHttpAgent({
|
||||
torPort?: number;
|
||||
retry: number;
|
||||
}): NodeAgent | undefined {
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
const { HttpProxyAgent } = require('http-proxy-agent');
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent');
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent');
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
/* eslint-enable @typescript-eslint/no-require-imports */
|
||||
|
||||
if (torPort) {
|
||||
return new SocksProxyAgent(`socks5h://tor${retry}@127.0.0.1:${torPort}`);
|
||||
@ -128,7 +126,8 @@ export async function fetchData(url: string, options: fetchDataOptions = {}) {
|
||||
if (!options.signal && options.timeout) {
|
||||
const controller = new AbortController();
|
||||
|
||||
options.signal = controller.signal;
|
||||
// Temporary workaround until @types/node-fetch is compatible with @types/node
|
||||
options.signal = controller.signal as FetchAbortSignal;
|
||||
|
||||
// Define timeout in seconds
|
||||
timeout = setTimeout(() => {
|
||||
@ -223,7 +222,8 @@ export const fetchGetUrlFunc =
|
||||
|
||||
if (_signal) {
|
||||
const controller = new AbortController();
|
||||
signal = controller.signal;
|
||||
// Temporary workaround until @types/node-fetch is compatible with @types/node
|
||||
signal = controller.signal as FetchAbortSignal;
|
||||
_signal.addListener(() => {
|
||||
controller.abort();
|
||||
});
|
||||
@ -257,113 +257,18 @@ export const fetchGetUrlFunc =
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||
|
||||
// caching to improve performance
|
||||
const oracleMapper = new Map();
|
||||
const multicallMapper = new Map();
|
||||
|
||||
export type getProviderOptions = fetchDataOptions & {
|
||||
pollingInterval?: number;
|
||||
gasPriceOracle?: string;
|
||||
gasStationApi?: string;
|
||||
};
|
||||
|
||||
export function getGasOraclePlugin(networkKey: string, fetchOptions?: getProviderOptions) {
|
||||
const gasStationApi = fetchOptions?.gasStationApi || 'https://gasstation.polygon.technology/v2';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
return new FetchUrlFeeDataNetworkPlugin(gasStationApi, async (fetchFeeData, provider, request) => {
|
||||
if (!oracleMapper.has(networkKey)) {
|
||||
oracleMapper.set(networkKey, GasPriceOracle__factory.connect(fetchOptions?.gasPriceOracle as string, provider));
|
||||
}
|
||||
if (!multicallMapper.has(networkKey)) {
|
||||
multicallMapper.set(
|
||||
networkKey,
|
||||
Multicall__factory.connect('0xcA11bde05977b3631167028862bE2a173976CA11', provider),
|
||||
);
|
||||
}
|
||||
const Oracle = oracleMapper.get(networkKey) as GasPriceOracle;
|
||||
const Multicall = multicallMapper.get(networkKey) as Multicall;
|
||||
|
||||
const [timestamp, heartbeat, feePerGas, priorityFeePerGas] = await multicall(Multicall, [
|
||||
{
|
||||
contract: Oracle,
|
||||
name: 'timestamp',
|
||||
},
|
||||
{
|
||||
contract: Oracle,
|
||||
name: 'heartbeat',
|
||||
},
|
||||
{
|
||||
contract: Oracle,
|
||||
name: 'maxFeePerGas',
|
||||
},
|
||||
{
|
||||
contract: Oracle,
|
||||
name: 'maxPriorityFeePerGas',
|
||||
},
|
||||
]);
|
||||
|
||||
const isOutdated = Number(timestamp) <= Date.now() / 1000 - Number(heartbeat);
|
||||
|
||||
if (!isOutdated) {
|
||||
const maxPriorityFeePerGas = (priorityFeePerGas * BigInt(13)) / BigInt(10);
|
||||
const maxFeePerGas = feePerGas * BigInt(2) + maxPriorityFeePerGas;
|
||||
|
||||
return {
|
||||
gasPrice: maxFeePerGas,
|
||||
maxFeePerGas,
|
||||
maxPriorityFeePerGas,
|
||||
};
|
||||
}
|
||||
|
||||
const fetchReq = new FetchRequest(gasStationApi);
|
||||
fetchReq.getUrlFunc = fetchGetUrlFunc(fetchOptions);
|
||||
if (isNode) {
|
||||
// Prevent Cloudflare from blocking our request in node.js
|
||||
fetchReq.setHeader('User-Agent', 'ethers');
|
||||
}
|
||||
|
||||
const [
|
||||
{
|
||||
bodyJson: { fast },
|
||||
},
|
||||
{ gasPrice },
|
||||
] = await Promise.all([fetchReq.send(), fetchFeeData()]);
|
||||
|
||||
return {
|
||||
gasPrice,
|
||||
maxFeePerGas: parseUnits(`${fast.maxFee}`, 9),
|
||||
maxPriorityFeePerGas: parseUnits(`${fast.maxPriorityFee}`, 9),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export async function getProvider(rpcUrl: string, fetchOptions?: getProviderOptions): Promise<JsonRpcProvider> {
|
||||
const fetchReq = new FetchRequest(rpcUrl);
|
||||
fetchReq.getUrlFunc = fetchGetUrlFunc(fetchOptions);
|
||||
// omit network plugins and mimic registerEth function (required for polygon)
|
||||
const _staticNetwork = await new JsonRpcProvider(fetchReq).getNetwork();
|
||||
const ensPlugin = _staticNetwork.getPlugin('org.ethers.plugins.network.Ens');
|
||||
const gasCostPlugin = _staticNetwork.getPlugin('org.ethers.plugins.network.GasCost');
|
||||
const gasStationPlugin = <FetchUrlFeeDataNetworkPlugin>(
|
||||
_staticNetwork.getPlugin('org.ethers.plugins.network.FetchUrlFeeDataPlugin')
|
||||
);
|
||||
const staticNetwork = new Network(_staticNetwork.name, _staticNetwork.chainId);
|
||||
if (ensPlugin) {
|
||||
staticNetwork.attachPlugin(ensPlugin);
|
||||
}
|
||||
if (gasCostPlugin) {
|
||||
staticNetwork.attachPlugin(gasCostPlugin);
|
||||
}
|
||||
if (fetchOptions?.gasPriceOracle) {
|
||||
staticNetwork.attachPlugin(getGasOraclePlugin(`${_staticNetwork.chainId}_${rpcUrl}`, fetchOptions));
|
||||
} else if (gasStationPlugin) {
|
||||
staticNetwork.attachPlugin(gasStationPlugin);
|
||||
}
|
||||
const staticNetwork = await new JsonRpcProvider(fetchReq).getNetwork();
|
||||
const provider = new JsonRpcProvider(fetchReq, staticNetwork, {
|
||||
staticNetwork,
|
||||
pollingInterval: fetchOptions?.pollingInterval || 1000,
|
||||
});
|
||||
provider.pollingInterval = fetchOptions?.pollingInterval || 1000;
|
||||
return provider;
|
||||
}
|
||||
|
||||
@ -373,7 +278,7 @@ export function getProviderWithNetId(
|
||||
config: Config,
|
||||
fetchOptions?: getProviderOptions,
|
||||
): JsonRpcProvider {
|
||||
const { networkName, reverseRecordsContract, gasPriceOracleContract, gasStationApi, pollInterval } = config;
|
||||
const { networkName, reverseRecordsContract, pollInterval } = config;
|
||||
const hasEns = Boolean(reverseRecordsContract);
|
||||
|
||||
const fetchReq = new FetchRequest(rpcUrl);
|
||||
@ -382,24 +287,13 @@ export function getProviderWithNetId(
|
||||
if (hasEns) {
|
||||
staticNetwork.attachPlugin(new EnsPlugin(null, Number(netId)));
|
||||
}
|
||||
|
||||
staticNetwork.attachPlugin(new GasCostPlugin());
|
||||
|
||||
if (gasPriceOracleContract) {
|
||||
staticNetwork.attachPlugin(
|
||||
getGasOraclePlugin(`${netId}_${rpcUrl}`, {
|
||||
gasPriceOracle: gasPriceOracleContract,
|
||||
gasStationApi,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const provider = new JsonRpcProvider(fetchReq, staticNetwork, {
|
||||
staticNetwork,
|
||||
pollingInterval: fetchOptions?.pollingInterval || pollInterval * 1000,
|
||||
});
|
||||
|
||||
provider.pollingInterval = fetchOptions?.pollingInterval || pollInterval * 1000;
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
|
@ -1,43 +1,45 @@
|
||||
import { getAddress, namehash, parseEther } from 'ethers';
|
||||
import type { Aggregator } from '@tornado/contracts';
|
||||
import type { RelayerStructOutput } from '@tornado/contracts/dist/contracts/Governance/Aggregator/Aggregator';
|
||||
import { getAddress, parseEther } from 'ethers';
|
||||
import { sleep } from './utils';
|
||||
import { NetId, NetIdType, Config } from './networkConfig';
|
||||
import { fetchData, fetchDataOptions } from './providers';
|
||||
import { ajv, jobsSchema, getStatusSchema } from './schemas';
|
||||
import type { snarkProofs } from './websnark';
|
||||
import { CachedRelayerInfo } from './events/base';
|
||||
|
||||
export const MIN_FEE = 0.1;
|
||||
|
||||
export const MAX_FEE = 0.6;
|
||||
|
||||
export const MIN_STAKE_BALANCE = parseEther('500');
|
||||
|
||||
export interface RelayerParams {
|
||||
ensName: string;
|
||||
relayerAddress?: string;
|
||||
relayerAddress: string;
|
||||
}
|
||||
|
||||
export interface Relayer {
|
||||
/**
|
||||
* Info from relayer status
|
||||
*/
|
||||
export type RelayerInfo = RelayerParams & {
|
||||
netId: NetIdType;
|
||||
url: string;
|
||||
hostname: string;
|
||||
rewardAccount: string;
|
||||
instances: string[];
|
||||
stakeBalance?: string;
|
||||
gasPrice?: number;
|
||||
ethPrices?: {
|
||||
[key in string]: string;
|
||||
};
|
||||
currentQueue: number;
|
||||
tornadoServiceFee: number;
|
||||
}
|
||||
|
||||
export type RelayerInfo = Relayer & {
|
||||
ensName: string;
|
||||
stakeBalance: bigint;
|
||||
relayerAddress: string;
|
||||
};
|
||||
|
||||
export type RelayerError = {
|
||||
hostname: string;
|
||||
relayerAddress?: string;
|
||||
errorMessage?: string;
|
||||
hasError: boolean;
|
||||
};
|
||||
|
||||
export interface RelayerStatus {
|
||||
@ -117,18 +119,18 @@ export function isRelayerUpdated(relayerVersion: string, netId: NetIdType) {
|
||||
return isUpdatedMajor && (Number(patch) >= 5 || netId !== NetId.MAINNET); // Patch checking - also backwards compatibility for Mainnet
|
||||
}
|
||||
|
||||
export function calculateScore({ stakeBalance, tornadoServiceFee }: RelayerInfo, minFee = 0.33, maxFee = 0.53) {
|
||||
if (tornadoServiceFee < minFee) {
|
||||
tornadoServiceFee = minFee;
|
||||
} else if (tornadoServiceFee >= maxFee) {
|
||||
export function calculateScore({ stakeBalance, tornadoServiceFee }: RelayerInfo) {
|
||||
if (tornadoServiceFee < MIN_FEE) {
|
||||
tornadoServiceFee = MIN_FEE;
|
||||
} else if (tornadoServiceFee >= MAX_FEE) {
|
||||
return BigInt(0);
|
||||
}
|
||||
|
||||
const serviceFeeCoefficient = (tornadoServiceFee - minFee) ** 2;
|
||||
const feeDiffCoefficient = 1 / (maxFee - minFee) ** 2;
|
||||
const serviceFeeCoefficient = (tornadoServiceFee - MIN_FEE) ** 2;
|
||||
const feeDiffCoefficient = 1 / (MAX_FEE - MIN_FEE) ** 2;
|
||||
const coefficientsMultiplier = 1 - feeDiffCoefficient * serviceFeeCoefficient;
|
||||
|
||||
return BigInt(Math.floor(Number(stakeBalance) * coefficientsMultiplier));
|
||||
return BigInt(Math.floor(Number(stakeBalance || '0') * coefficientsMultiplier));
|
||||
}
|
||||
|
||||
export function getWeightRandom(weightsScores: bigint[], random: bigint) {
|
||||
@ -159,20 +161,13 @@ export function getSupportedInstances(instanceList: RelayerInstanceList) {
|
||||
return rawList.map((l) => getAddress(l));
|
||||
}
|
||||
|
||||
export function pickWeightedRandomRelayer(relayers: RelayerInfo[], netId: NetIdType) {
|
||||
let minFee: number, maxFee: number;
|
||||
|
||||
if (netId !== NetId.MAINNET) {
|
||||
minFee = 0.01;
|
||||
maxFee = 0.3;
|
||||
}
|
||||
|
||||
const weightsScores = relayers.map((el) => calculateScore(el, minFee, maxFee));
|
||||
export function pickWeightedRandomRelayer(relayers: RelayerInfo[]) {
|
||||
const weightsScores = relayers.map((el) => calculateScore(el));
|
||||
const totalWeight = weightsScores.reduce((acc, curr) => {
|
||||
return (acc = acc + curr);
|
||||
}, BigInt('0'));
|
||||
|
||||
const random = BigInt(Number(totalWeight) * Math.random());
|
||||
const random = BigInt(Math.floor(Number(totalWeight) * Math.random()));
|
||||
const weightRandomIndex = getWeightRandom(weightsScores, random);
|
||||
|
||||
return relayers[weightRandomIndex];
|
||||
@ -181,7 +176,6 @@ export function pickWeightedRandomRelayer(relayers: RelayerInfo[], netId: NetIdT
|
||||
export interface RelayerClientConstructor {
|
||||
netId: NetIdType;
|
||||
config: Config;
|
||||
Aggregator: Aggregator;
|
||||
fetchDataOptions?: fetchDataOptions;
|
||||
}
|
||||
|
||||
@ -192,14 +186,12 @@ export type RelayerClientWithdraw = snarkProofs & {
|
||||
export class RelayerClient {
|
||||
netId: NetIdType;
|
||||
config: Config;
|
||||
Aggregator: Aggregator;
|
||||
selectedRelayer?: Relayer;
|
||||
selectedRelayer?: RelayerInfo;
|
||||
fetchDataOptions?: fetchDataOptions;
|
||||
|
||||
constructor({ netId, config, Aggregator, fetchDataOptions }: RelayerClientConstructor) {
|
||||
constructor({ netId, config, fetchDataOptions }: RelayerClientConstructor) {
|
||||
this.netId = netId;
|
||||
this.config = config;
|
||||
this.Aggregator = Aggregator;
|
||||
this.fetchDataOptions = fetchDataOptions;
|
||||
}
|
||||
|
||||
@ -251,101 +243,54 @@ export class RelayerClient {
|
||||
return status;
|
||||
}
|
||||
|
||||
async filterRelayer(
|
||||
curr: RelayerStructOutput,
|
||||
relayer: RelayerParams,
|
||||
subdomains: string[],
|
||||
debugRelayer: boolean = false,
|
||||
): Promise<RelayerInfo | RelayerError> {
|
||||
const { relayerEnsSubdomain } = this.config;
|
||||
const subdomainIndex = subdomains.indexOf(relayerEnsSubdomain);
|
||||
const mainnetSubdomain = curr.records[0];
|
||||
const hostname = curr.records[subdomainIndex];
|
||||
const isHostWithProtocol = hostname.includes('http');
|
||||
|
||||
const { owner, balance: stakeBalance, isRegistered } = curr;
|
||||
async filterRelayer(relayer: CachedRelayerInfo): Promise<RelayerInfo | RelayerError | undefined> {
|
||||
const hostname = relayer.hostnames[this.netId];
|
||||
const { ensName, relayerAddress } = relayer;
|
||||
|
||||
const isOwner = !relayerAddress || relayerAddress === owner;
|
||||
const hasMinBalance = stakeBalance >= MIN_STAKE_BALANCE;
|
||||
if (!hostname) {
|
||||
return;
|
||||
}
|
||||
|
||||
const preCondition =
|
||||
hostname && isOwner && mainnetSubdomain && isRegistered && hasMinBalance && !isHostWithProtocol;
|
||||
try {
|
||||
const status = await this.askRelayerStatus({ hostname, relayerAddress });
|
||||
|
||||
if (preCondition || debugRelayer) {
|
||||
try {
|
||||
const status = await this.askRelayerStatus({ hostname, relayerAddress });
|
||||
|
||||
return {
|
||||
netId: status.netId,
|
||||
url: status.url,
|
||||
hostname,
|
||||
ensName,
|
||||
stakeBalance,
|
||||
relayerAddress,
|
||||
rewardAccount: getAddress(status.rewardAccount),
|
||||
instances: getSupportedInstances(status.instances),
|
||||
gasPrice: status.gasPrices?.fast,
|
||||
ethPrices: status.ethPrices,
|
||||
currentQueue: status.currentQueue,
|
||||
tornadoServiceFee: status.tornadoServiceFee,
|
||||
} as RelayerInfo;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (err: any) {
|
||||
if (debugRelayer) {
|
||||
throw err;
|
||||
}
|
||||
return {
|
||||
hostname,
|
||||
relayerAddress,
|
||||
errorMessage: err.message,
|
||||
} as RelayerError;
|
||||
}
|
||||
} else {
|
||||
if (debugRelayer) {
|
||||
const errMsg = `Relayer ${hostname} condition not met`;
|
||||
throw new Error(errMsg);
|
||||
}
|
||||
return {
|
||||
netId: status.netId,
|
||||
url: status.url,
|
||||
hostname,
|
||||
ensName,
|
||||
relayerAddress,
|
||||
rewardAccount: getAddress(status.rewardAccount),
|
||||
instances: getSupportedInstances(status.instances),
|
||||
stakeBalance: relayer.stakeBalance,
|
||||
gasPrice: status.gasPrices?.fast,
|
||||
ethPrices: status.ethPrices,
|
||||
currentQueue: status.currentQueue,
|
||||
tornadoServiceFee: status.tornadoServiceFee,
|
||||
} as RelayerInfo;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (err: any) {
|
||||
return {
|
||||
hostname,
|
||||
relayerAddress,
|
||||
errorMessage: `Relayer ${hostname} condition not met`,
|
||||
};
|
||||
errorMessage: err.message,
|
||||
hasError: true,
|
||||
} as RelayerError;
|
||||
}
|
||||
}
|
||||
|
||||
async getValidRelayers(
|
||||
// this should be ascending order of events
|
||||
relayers: RelayerParams[],
|
||||
subdomains: string[],
|
||||
debugRelayer: boolean = false,
|
||||
): Promise<{
|
||||
async getValidRelayers(relayers: CachedRelayerInfo[]): Promise<{
|
||||
validRelayers: RelayerInfo[];
|
||||
invalidRelayers: RelayerError[];
|
||||
}> {
|
||||
const relayersSet = new Set();
|
||||
|
||||
const uniqueRelayers = relayers.reverse().filter(({ ensName }) => {
|
||||
if (!relayersSet.has(ensName)) {
|
||||
relayersSet.add(ensName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const relayerNameHashes = uniqueRelayers.map((r) => namehash(r.ensName));
|
||||
|
||||
const relayersData = await this.Aggregator.relayersData.staticCall(relayerNameHashes, subdomains);
|
||||
|
||||
const invalidRelayers: RelayerError[] = [];
|
||||
|
||||
const validRelayers = (
|
||||
await Promise.all(
|
||||
relayersData.map((curr, index) => this.filterRelayer(curr, uniqueRelayers[index], subdomains, debugRelayer)),
|
||||
)
|
||||
).filter((r) => {
|
||||
if ((r as RelayerError).errorMessage) {
|
||||
invalidRelayers.push(r);
|
||||
const validRelayers = (await Promise.all(relayers.map((relayer) => this.filterRelayer(relayer)))).filter((r) => {
|
||||
if (!r) {
|
||||
return false;
|
||||
}
|
||||
if ((r as RelayerError).hasError) {
|
||||
invalidRelayers.push(r as RelayerError);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -358,11 +303,11 @@ export class RelayerClient {
|
||||
}
|
||||
|
||||
pickWeightedRandomRelayer(relayers: RelayerInfo[]) {
|
||||
return pickWeightedRandomRelayer(relayers, this.netId);
|
||||
return pickWeightedRandomRelayer(relayers);
|
||||
}
|
||||
|
||||
async tornadoWithdraw({ contract, proof, args }: RelayerClientWithdraw) {
|
||||
const { url } = this.selectedRelayer as Relayer;
|
||||
const { url } = this.selectedRelayer as RelayerInfo;
|
||||
|
||||
const withdrawResponse = (await fetchData(`${url}v1/tornadoWithdraw`, {
|
||||
...this.fetchDataOptions,
|
||||
|
@ -10,7 +10,7 @@ ajv.addKeyword({
|
||||
try {
|
||||
BigInt(data);
|
||||
return true;
|
||||
} catch (e) {
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
@ -3,7 +3,6 @@
|
||||
/* eslint-disable */
|
||||
export { ENS__factory } from "./ENS__factory";
|
||||
export { ERC20__factory } from "./ERC20__factory";
|
||||
export { GasPriceOracle__factory } from "./GasPriceOracle__factory";
|
||||
export { Multicall__factory } from "./Multicall__factory";
|
||||
export { OffchainOracle__factory } from "./OffchainOracle__factory";
|
||||
export { OvmGasPriceOracle__factory } from "./OvmGasPriceOracle__factory";
|
||||
|
@ -3,7 +3,6 @@
|
||||
/* eslint-disable */
|
||||
export type { ENS } from "./ENS";
|
||||
export type { ERC20 } from "./ERC20";
|
||||
export type { GasPriceOracle } from "./GasPriceOracle";
|
||||
export type { Multicall } from "./Multicall";
|
||||
export type { OffchainOracle } from "./OffchainOracle";
|
||||
export type { OvmGasPriceOracle } from "./OvmGasPriceOracle";
|
||||
@ -11,7 +10,6 @@ export type { ReverseRecords } from "./ReverseRecords";
|
||||
export * as factories from "./factories";
|
||||
export { ENS__factory } from "./factories/ENS__factory";
|
||||
export { ERC20__factory } from "./factories/ERC20__factory";
|
||||
export { GasPriceOracle__factory } from "./factories/GasPriceOracle__factory";
|
||||
export { Multicall__factory } from "./factories/Multicall__factory";
|
||||
export { OffchainOracle__factory } from "./factories/OffchainOracle__factory";
|
||||
export { OvmGasPriceOracle__factory } from "./factories/OvmGasPriceOracle__factory";
|
||||
|
@ -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": "es2018", /* 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. */
|
||||
|
@ -1,4 +1,3 @@
|
||||
const esbuild = require('esbuild');
|
||||
const path = require('path');
|
||||
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
|
||||
|
||||
@ -8,7 +7,6 @@ const esbuildLoader = {
|
||||
options: {
|
||||
loader: 'ts',
|
||||
target: 'es2016',
|
||||
implementation: esbuild
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user