forked from tornado-packages/tornado-core
tornado-core 1.0.5
* support saving relayers
This commit is contained in:
parent
3df238e55f
commit
e506c373de
48
dist/events/base.d.ts
vendored
48
dist/events/base.d.ts
vendored
@ -1,8 +1,9 @@
|
|||||||
import { BaseContract, Provider, EventLog, ContractEventName } from 'ethers';
|
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 { BatchEventsService, BatchBlockService, BatchTransactionService, BatchEventOnProgress, BatchBlockOnProgress } from '../batch';
|
||||||
import { fetchDataOptions } from '../providers';
|
import type { fetchDataOptions } from '../providers';
|
||||||
import type { NetIdType } from '../networkConfig';
|
import type { NetIdType, SubdomainMap } from '../networkConfig';
|
||||||
|
import { RelayerParams } from '../relayerClient';
|
||||||
import type { BaseEvents, CachedEvents, MinimalEvents, DepositsEvents, WithdrawalsEvents, EncryptedNotesEvents, AllGovernanceEvents, RegistersEvents, EchoEvents } from './types';
|
import type { BaseEvents, CachedEvents, MinimalEvents, DepositsEvents, WithdrawalsEvents, EncryptedNotesEvents, AllGovernanceEvents, RegistersEvents, EchoEvents } from './types';
|
||||||
export declare const DEPOSIT = "deposit";
|
export declare const DEPOSIT = "deposit";
|
||||||
export declare const WITHDRAWAL = "withdrawal";
|
export declare const WITHDRAWAL = "withdrawal";
|
||||||
@ -169,17 +170,37 @@ export declare class BaseGovernanceService extends BaseEventsService<AllGovernan
|
|||||||
fromBlock: number;
|
fromBlock: number;
|
||||||
}): Promise<BaseEvents<AllGovernanceEvents>>;
|
}): 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[];
|
||||||
|
}
|
||||||
export type BaseRegistryServiceConstructor = {
|
export type BaseRegistryServiceConstructor = {
|
||||||
netId: NetIdType;
|
netId: NetIdType;
|
||||||
provider: Provider;
|
provider: Provider;
|
||||||
graphApi?: string;
|
graphApi?: string;
|
||||||
subgraphName?: string;
|
subgraphName?: string;
|
||||||
RelayerRegistry: RelayerRegistry;
|
RelayerRegistry: RelayerRegistry;
|
||||||
|
Aggregator: Aggregator;
|
||||||
|
relayerEnsSubdomains: SubdomainMap;
|
||||||
deployedBlock?: number;
|
deployedBlock?: number;
|
||||||
fetchDataOptions?: fetchDataOptions;
|
fetchDataOptions?: fetchDataOptions;
|
||||||
};
|
};
|
||||||
export declare class BaseRegistryService extends BaseEventsService<RegistersEvents> {
|
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;
|
getInstanceName(): string;
|
||||||
getType(): string;
|
getType(): string;
|
||||||
getGraphMethod(): string;
|
getGraphMethod(): string;
|
||||||
@ -190,5 +211,22 @@ export declare class BaseRegistryService extends BaseEventsService<RegistersEven
|
|||||||
logIndex: number;
|
logIndex: number;
|
||||||
transactionHash: string;
|
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>;
|
||||||
}
|
}
|
||||||
|
1882
dist/index.js
vendored
1882
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
1883
dist/index.mjs
vendored
1883
dist/index.mjs
vendored
File diff suppressed because it is too large
Load Diff
299
dist/index.umd.js
vendored
299
dist/index.umd.js
vendored
@ -59069,9 +59069,12 @@ class NoteAccount {
|
|||||||
/* harmony export */ oW: () => (/* binding */ WITHDRAWAL),
|
/* harmony export */ oW: () => (/* binding */ WITHDRAWAL),
|
||||||
/* harmony export */ uw: () => (/* binding */ BaseEventsService)
|
/* harmony export */ uw: () => (/* binding */ BaseEventsService)
|
||||||
/* harmony export */ });
|
/* harmony export */ });
|
||||||
/* harmony import */ var ethers__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(30031);
|
/* harmony import */ var ethers__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(30031);
|
||||||
|
/* harmony import */ var ethers__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(64563);
|
||||||
|
/* harmony import */ var ethers__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(99770);
|
||||||
/* harmony import */ var _graphql__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(52049);
|
/* harmony import */ var _graphql__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(52049);
|
||||||
/* harmony import */ var _batch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9723);
|
/* harmony import */ var _batch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9723);
|
||||||
|
/* harmony import */ var _relayerClient__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(57194);
|
||||||
|
|
||||||
var __defProp = Object.defineProperty;
|
var __defProp = Object.defineProperty;
|
||||||
var __defProps = Object.defineProperties;
|
var __defProps = Object.defineProperties;
|
||||||
@ -59118,6 +59121,7 @@ var __async = (__this, __arguments, generator) => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const DEPOSIT = "deposit";
|
const DEPOSIT = "deposit";
|
||||||
const WITHDRAWAL = "withdrawal";
|
const WITHDRAWAL = "withdrawal";
|
||||||
class BaseEventsService {
|
class BaseEventsService {
|
||||||
@ -59129,13 +59133,13 @@ class BaseEventsService {
|
|||||||
contract,
|
contract,
|
||||||
type = "",
|
type = "",
|
||||||
deployedBlock = 0,
|
deployedBlock = 0,
|
||||||
fetchDataOptions: fetchDataOptions2
|
fetchDataOptions
|
||||||
}) {
|
}) {
|
||||||
this.netId = netId;
|
this.netId = netId;
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.graphApi = graphApi;
|
this.graphApi = graphApi;
|
||||||
this.subgraphName = subgraphName;
|
this.subgraphName = subgraphName;
|
||||||
this.fetchDataOptions = fetchDataOptions2;
|
this.fetchDataOptions = fetchDataOptions;
|
||||||
this.contract = contract;
|
this.contract = contract;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.deployedBlock = deployedBlock;
|
this.deployedBlock = deployedBlock;
|
||||||
@ -59345,9 +59349,9 @@ class BaseTornadoService extends BaseEventsService {
|
|||||||
amount,
|
amount,
|
||||||
currency,
|
currency,
|
||||||
deployedBlock,
|
deployedBlock,
|
||||||
fetchDataOptions: fetchDataOptions2
|
fetchDataOptions
|
||||||
}) {
|
}) {
|
||||||
super({ netId, provider, graphApi, subgraphName, contract: Tornado, type, deployedBlock, fetchDataOptions: fetchDataOptions2 });
|
super({ netId, provider, graphApi, subgraphName, contract: Tornado, type, deployedBlock, fetchDataOptions });
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
this.currency = currency;
|
this.currency = currency;
|
||||||
this.batchTransactionService = new _batch__WEBPACK_IMPORTED_MODULE_1__/* .BatchTransactionService */ .AF({
|
this.batchTransactionService = new _batch__WEBPACK_IMPORTED_MODULE_1__/* .BatchTransactionService */ .AF({
|
||||||
@ -59407,7 +59411,7 @@ class BaseTornadoService extends BaseEventsService {
|
|||||||
logIndex,
|
logIndex,
|
||||||
transactionHash,
|
transactionHash,
|
||||||
nullifierHash: String(nullifierHash),
|
nullifierHash: String(nullifierHash),
|
||||||
to: (0,ethers__WEBPACK_IMPORTED_MODULE_2__/* .getAddress */ .b)(to),
|
to: (0,ethers__WEBPACK_IMPORTED_MODULE_3__/* .getAddress */ .b)(to),
|
||||||
fee: String(fee)
|
fee: String(fee)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -59441,9 +59445,9 @@ class BaseEchoService extends BaseEventsService {
|
|||||||
subgraphName,
|
subgraphName,
|
||||||
Echoer,
|
Echoer,
|
||||||
deployedBlock,
|
deployedBlock,
|
||||||
fetchDataOptions: fetchDataOptions2
|
fetchDataOptions
|
||||||
}) {
|
}) {
|
||||||
super({ netId, provider, graphApi, subgraphName, contract: Echoer, deployedBlock, fetchDataOptions: fetchDataOptions2 });
|
super({ netId, provider, graphApi, subgraphName, contract: Echoer, deployedBlock, fetchDataOptions });
|
||||||
}
|
}
|
||||||
getInstanceName() {
|
getInstanceName() {
|
||||||
return `echo_${this.netId}`;
|
return `echo_${this.netId}`;
|
||||||
@ -59492,9 +59496,9 @@ class BaseEncryptedNotesService extends BaseEventsService {
|
|||||||
subgraphName,
|
subgraphName,
|
||||||
Router,
|
Router,
|
||||||
deployedBlock,
|
deployedBlock,
|
||||||
fetchDataOptions: fetchDataOptions2
|
fetchDataOptions
|
||||||
}) {
|
}) {
|
||||||
super({ netId, provider, graphApi, subgraphName, contract: Router, deployedBlock, fetchDataOptions: fetchDataOptions2 });
|
super({ netId, provider, graphApi, subgraphName, contract: Router, deployedBlock, fetchDataOptions });
|
||||||
}
|
}
|
||||||
getInstanceName() {
|
getInstanceName() {
|
||||||
return `encrypted_notes_${this.netId}`;
|
return `encrypted_notes_${this.netId}`;
|
||||||
@ -59531,9 +59535,9 @@ class BaseGovernanceService extends BaseEventsService {
|
|||||||
subgraphName,
|
subgraphName,
|
||||||
Governance,
|
Governance,
|
||||||
deployedBlock,
|
deployedBlock,
|
||||||
fetchDataOptions: fetchDataOptions2
|
fetchDataOptions
|
||||||
}) {
|
}) {
|
||||||
super({ netId, provider, graphApi, subgraphName, contract: Governance, deployedBlock, fetchDataOptions: fetchDataOptions2 });
|
super({ netId, provider, graphApi, subgraphName, contract: Governance, deployedBlock, fetchDataOptions });
|
||||||
this.batchTransactionService = new _batch__WEBPACK_IMPORTED_MODULE_1__/* .BatchTransactionService */ .AF({
|
this.batchTransactionService = new _batch__WEBPACK_IMPORTED_MODULE_1__/* .BatchTransactionService */ .AF({
|
||||||
provider,
|
provider,
|
||||||
onProgress: this.updateTransactionProgress
|
onProgress: this.updateTransactionProgress
|
||||||
@ -59634,10 +59638,15 @@ class BaseRegistryService extends BaseEventsService {
|
|||||||
graphApi,
|
graphApi,
|
||||||
subgraphName,
|
subgraphName,
|
||||||
RelayerRegistry,
|
RelayerRegistry,
|
||||||
|
Aggregator,
|
||||||
|
relayerEnsSubdomains,
|
||||||
deployedBlock,
|
deployedBlock,
|
||||||
fetchDataOptions: fetchDataOptions2
|
fetchDataOptions
|
||||||
}) {
|
}) {
|
||||||
super({ netId, provider, graphApi, subgraphName, contract: RelayerRegistry, deployedBlock, fetchDataOptions: fetchDataOptions2 });
|
super({ netId, provider, graphApi, subgraphName, contract: RelayerRegistry, deployedBlock, fetchDataOptions });
|
||||||
|
this.Aggregator = Aggregator;
|
||||||
|
this.relayerEnsSubdomains = relayerEnsSubdomains;
|
||||||
|
this.updateInterval = 86400;
|
||||||
}
|
}
|
||||||
getInstanceName() {
|
getInstanceName() {
|
||||||
return `registered_${this.netId}`;
|
return `registered_${this.netId}`;
|
||||||
@ -59665,9 +59674,102 @@ class BaseRegistryService extends BaseEventsService {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fetchRelayers() {
|
/**
|
||||||
|
* Get saved or cached relayers
|
||||||
|
*/
|
||||||
|
getRelayersFromDB() {
|
||||||
return __async(this, null, function* () {
|
return __async(this, null, function* () {
|
||||||
return (yield this.updateEvents()).events;
|
return {
|
||||||
|
timestamp: 0,
|
||||||
|
relayers: []
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Relayers from remote cache (Either from local cache, CDN, or from IPFS)
|
||||||
|
*/
|
||||||
|
getRelayersFromCache() {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
return {
|
||||||
|
timestamp: 0,
|
||||||
|
relayers: []
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getSavedRelayers() {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
let cachedRelayers = yield this.getRelayersFromDB();
|
||||||
|
if (!cachedRelayers || !cachedRelayers.relayers.length) {
|
||||||
|
cachedRelayers = yield this.getRelayersFromCache();
|
||||||
|
}
|
||||||
|
return cachedRelayers;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getLatestRelayers() {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
const registerEvents = (yield this.updateEvents()).events;
|
||||||
|
const subdomains = Object.values(this.relayerEnsSubdomains);
|
||||||
|
const registerSet = /* @__PURE__ */ new Set();
|
||||||
|
const uniqueRegisters = registerEvents.reverse().filter(({ ensName }) => {
|
||||||
|
if (!registerSet.has(ensName)) {
|
||||||
|
registerSet.add(ensName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
const relayerNameHashes = uniqueRegisters.map((r) => (0,ethers__WEBPACK_IMPORTED_MODULE_4__/* .namehash */ .kM)(r.ensName));
|
||||||
|
const [relayersData, timestamp] = yield Promise.all([
|
||||||
|
this.Aggregator.relayersData.staticCall(relayerNameHashes, subdomains),
|
||||||
|
this.provider.getBlock("latest").then((b) => Number(b == null ? void 0 : b.timestamp))
|
||||||
|
]);
|
||||||
|
const relayers = relayersData.map(({ owner, balance: stakeBalance, records, isRegistered }, index) => {
|
||||||
|
const { ensName, relayerAddress } = uniqueRegisters[index];
|
||||||
|
const hostnames = {};
|
||||||
|
records.forEach((record, recordIndex) => {
|
||||||
|
if (record) {
|
||||||
|
hostnames[Number(Object.keys(this.relayerEnsSubdomains)[recordIndex])] = record;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const isOwner = !relayerAddress || relayerAddress === owner;
|
||||||
|
const hasMinBalance = stakeBalance >= _relayerClient__WEBPACK_IMPORTED_MODULE_2__/* .MIN_STAKE_BALANCE */ .pO;
|
||||||
|
const preCondition = Object.keys(hostnames).length && isOwner && isRegistered && hasMinBalance;
|
||||||
|
if (preCondition) {
|
||||||
|
return {
|
||||||
|
ensName,
|
||||||
|
relayerAddress,
|
||||||
|
isRegistered,
|
||||||
|
owner,
|
||||||
|
stakeBalance: (0,ethers__WEBPACK_IMPORTED_MODULE_5__/* .formatEther */ .ck)(stakeBalance),
|
||||||
|
hostnames
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}).filter((r) => r);
|
||||||
|
return {
|
||||||
|
timestamp,
|
||||||
|
relayers
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handle saving relayers
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
saveRelayers(_0) {
|
||||||
|
return __async(this, arguments, function* ({ timestamp, relayers }) {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get cached or latest relayer and save to local
|
||||||
|
*/
|
||||||
|
updateRelayers() {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
let { timestamp, relayers } = yield this.getSavedRelayers();
|
||||||
|
if (!relayers.length || timestamp + this.updateInterval < Math.floor(Date.now() / 1e3)) {
|
||||||
|
console.log("\nUpdating relayers from registry\n");
|
||||||
|
({ timestamp, relayers } = yield this.getLatestRelayers());
|
||||||
|
yield this.saveRelayers({ timestamp, relayers });
|
||||||
|
}
|
||||||
|
return { timestamp, relayers };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61138,6 +61240,7 @@ function multicall(Multicall2, calls) {
|
|||||||
/* harmony export */ Zh: () => (/* binding */ getInstanceByAddress),
|
/* harmony export */ Zh: () => (/* binding */ getInstanceByAddress),
|
||||||
/* harmony export */ cF: () => (/* binding */ getSubdomains),
|
/* harmony export */ cF: () => (/* binding */ getSubdomains),
|
||||||
/* harmony export */ cX: () => (/* binding */ customConfig),
|
/* harmony export */ cX: () => (/* binding */ customConfig),
|
||||||
|
/* harmony export */ o2: () => (/* binding */ getRelayerEnsSubdomains),
|
||||||
/* harmony export */ sb: () => (/* binding */ defaultConfig),
|
/* harmony export */ sb: () => (/* binding */ defaultConfig),
|
||||||
/* harmony export */ zj: () => (/* binding */ getConfig),
|
/* harmony export */ zj: () => (/* binding */ getConfig),
|
||||||
/* harmony export */ zr: () => (/* binding */ NetId)
|
/* harmony export */ zr: () => (/* binding */ NetId)
|
||||||
@ -61679,10 +61782,6 @@ const defaultConfig = {
|
|||||||
tornadoSubgraph: "tornadocash/sepolia-tornado-subgraph",
|
tornadoSubgraph: "tornadocash/sepolia-tornado-subgraph",
|
||||||
subgraphs: {},
|
subgraphs: {},
|
||||||
rpcUrls: {
|
rpcUrls: {
|
||||||
pandaops: {
|
|
||||||
name: "ethpandaops",
|
|
||||||
url: "https://rpc.sepolia.ethpandaops.io"
|
|
||||||
},
|
|
||||||
sepolia: {
|
sepolia: {
|
||||||
name: "Sepolia RPC",
|
name: "Sepolia RPC",
|
||||||
url: "https://rpc.sepolia.org"
|
url: "https://rpc.sepolia.org"
|
||||||
@ -61694,6 +61793,10 @@ const defaultConfig = {
|
|||||||
onerpc: {
|
onerpc: {
|
||||||
name: "1rpc",
|
name: "1rpc",
|
||||||
url: "https://1rpc.io/sepolia"
|
url: "https://1rpc.io/sepolia"
|
||||||
|
},
|
||||||
|
ethpandaops: {
|
||||||
|
name: "ethpandaops",
|
||||||
|
url: "https://rpc.sepolia.ethpandaops.io"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tokens: {
|
tokens: {
|
||||||
@ -61772,6 +61875,13 @@ function getSubdomains() {
|
|||||||
const allConfig = getNetworkConfig();
|
const allConfig = getNetworkConfig();
|
||||||
return enabledChains.map((chain) => allConfig[chain].relayerEnsSubdomain);
|
return enabledChains.map((chain) => allConfig[chain].relayerEnsSubdomain);
|
||||||
}
|
}
|
||||||
|
function getRelayerEnsSubdomains() {
|
||||||
|
const allConfig = getNetworkConfig();
|
||||||
|
return Object.keys(allConfig).reduce((acc, chain) => {
|
||||||
|
acc[Number(chain)] = allConfig[Number(chain)].relayerEnsSubdomain;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
@ -71306,7 +71416,9 @@ class TornadoBrowserProvider extends BrowserProvider {
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
|
/* harmony export */ KN: () => (/* binding */ MAX_FEE),
|
||||||
/* harmony export */ OR: () => (/* binding */ RelayerClient),
|
/* harmony export */ OR: () => (/* binding */ RelayerClient),
|
||||||
|
/* harmony export */ Ss: () => (/* binding */ MIN_FEE),
|
||||||
/* harmony export */ XF: () => (/* binding */ getSupportedInstances),
|
/* harmony export */ XF: () => (/* binding */ getSupportedInstances),
|
||||||
/* harmony export */ c$: () => (/* binding */ getWeightRandom),
|
/* harmony export */ c$: () => (/* binding */ getWeightRandom),
|
||||||
/* harmony export */ mU: () => (/* binding */ isRelayerUpdated),
|
/* harmony export */ mU: () => (/* binding */ isRelayerUpdated),
|
||||||
@ -71317,7 +71429,6 @@ class TornadoBrowserProvider extends BrowserProvider {
|
|||||||
/* harmony export */ });
|
/* harmony export */ });
|
||||||
/* harmony import */ var ethers__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(99770);
|
/* harmony import */ var ethers__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(99770);
|
||||||
/* harmony import */ var ethers__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(30031);
|
/* harmony import */ var ethers__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(30031);
|
||||||
/* harmony import */ var ethers__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(64563);
|
|
||||||
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(67418);
|
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(67418);
|
||||||
/* harmony import */ var _networkConfig__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(59499);
|
/* harmony import */ var _networkConfig__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(59499);
|
||||||
/* harmony import */ var _providers__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(68434);
|
/* harmony import */ var _providers__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(68434);
|
||||||
@ -71367,6 +71478,8 @@ var __async = (__this, __arguments, generator) => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const MIN_FEE = 0.1;
|
||||||
|
const MAX_FEE = 0.6;
|
||||||
const MIN_STAKE_BALANCE = (0,ethers__WEBPACK_IMPORTED_MODULE_4__/* .parseEther */ .g5)("500");
|
const MIN_STAKE_BALANCE = (0,ethers__WEBPACK_IMPORTED_MODULE_4__/* .parseEther */ .g5)("500");
|
||||||
const semVerRegex = new RegExp("^(?<major>0|[1-9]\\d*)\\.(?<minor>0|[1-9]\\d*)\\.(?<patch>0|[1-9]\\d*)(?:-(?<prerelease>(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?<buildmetadata>[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$");
|
const semVerRegex = new RegExp("^(?<major>0|[1-9]\\d*)\\.(?<minor>0|[1-9]\\d*)\\.(?<patch>0|[1-9]\\d*)(?:-(?<prerelease>(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?<buildmetadata>[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$");
|
||||||
function parseSemanticVersion(version) {
|
function parseSemanticVersion(version) {
|
||||||
@ -71380,16 +71493,16 @@ function isRelayerUpdated(relayerVersion, netId) {
|
|||||||
if (prerelease) return false;
|
if (prerelease) return false;
|
||||||
return isUpdatedMajor && (Number(patch) >= 5 || netId !== _networkConfig__WEBPACK_IMPORTED_MODULE_1__/* .NetId */ .zr.MAINNET);
|
return isUpdatedMajor && (Number(patch) >= 5 || netId !== _networkConfig__WEBPACK_IMPORTED_MODULE_1__/* .NetId */ .zr.MAINNET);
|
||||||
}
|
}
|
||||||
function calculateScore({ stakeBalance, tornadoServiceFee }, minFee = 0.33, maxFee = 0.53) {
|
function calculateScore({ stakeBalance, tornadoServiceFee }) {
|
||||||
if (tornadoServiceFee < minFee) {
|
if (tornadoServiceFee < MIN_FEE) {
|
||||||
tornadoServiceFee = minFee;
|
tornadoServiceFee = MIN_FEE;
|
||||||
} else if (tornadoServiceFee >= maxFee) {
|
} else if (tornadoServiceFee >= MAX_FEE) {
|
||||||
return BigInt(0);
|
return BigInt(0);
|
||||||
}
|
}
|
||||||
const serviceFeeCoefficient = (tornadoServiceFee - minFee) ** 2;
|
const serviceFeeCoefficient = (tornadoServiceFee - MIN_FEE) ** 2;
|
||||||
const feeDiffCoefficient = 1 / (maxFee - minFee) ** 2;
|
const feeDiffCoefficient = 1 / (MAX_FEE - MIN_FEE) ** 2;
|
||||||
const coefficientsMultiplier = 1 - feeDiffCoefficient * serviceFeeCoefficient;
|
const coefficientsMultiplier = 1 - feeDiffCoefficient * serviceFeeCoefficient;
|
||||||
return BigInt(Math.floor(Number(stakeBalance) * coefficientsMultiplier));
|
return BigInt(Math.floor(Number(stakeBalance || "0") * coefficientsMultiplier));
|
||||||
}
|
}
|
||||||
function getWeightRandom(weightsScores, random) {
|
function getWeightRandom(weightsScores, random) {
|
||||||
for (let i = 0; i < weightsScores.length; i++) {
|
for (let i = 0; i < weightsScores.length; i++) {
|
||||||
@ -71406,25 +71519,19 @@ function getSupportedInstances(instanceList) {
|
|||||||
}).flat();
|
}).flat();
|
||||||
return rawList.map((l) => (0,ethers__WEBPACK_IMPORTED_MODULE_5__/* .getAddress */ .b)(l));
|
return rawList.map((l) => (0,ethers__WEBPACK_IMPORTED_MODULE_5__/* .getAddress */ .b)(l));
|
||||||
}
|
}
|
||||||
function pickWeightedRandomRelayer(relayers, netId) {
|
function pickWeightedRandomRelayer(relayers) {
|
||||||
let minFee, maxFee;
|
const weightsScores = relayers.map((el) => calculateScore(el));
|
||||||
if (netId !== _networkConfig__WEBPACK_IMPORTED_MODULE_1__/* .NetId */ .zr.MAINNET) {
|
|
||||||
minFee = 0.01;
|
|
||||||
maxFee = 0.3;
|
|
||||||
}
|
|
||||||
const weightsScores = relayers.map((el) => calculateScore(el, minFee, maxFee));
|
|
||||||
const totalWeight = weightsScores.reduce((acc, curr) => {
|
const totalWeight = weightsScores.reduce((acc, curr) => {
|
||||||
return acc = acc + curr;
|
return acc = acc + curr;
|
||||||
}, BigInt("0"));
|
}, BigInt("0"));
|
||||||
const random = BigInt(Number(totalWeight) * Math.random());
|
const random = BigInt(Math.floor(Number(totalWeight) * Math.random()));
|
||||||
const weightRandomIndex = getWeightRandom(weightsScores, random);
|
const weightRandomIndex = getWeightRandom(weightsScores, random);
|
||||||
return relayers[weightRandomIndex];
|
return relayers[weightRandomIndex];
|
||||||
}
|
}
|
||||||
class RelayerClient {
|
class RelayerClient {
|
||||||
constructor({ netId, config, Aggregator, fetchDataOptions: fetchDataOptions2 }) {
|
constructor({ netId, config, fetchDataOptions: fetchDataOptions2 }) {
|
||||||
this.netId = netId;
|
this.netId = netId;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.Aggregator = Aggregator;
|
|
||||||
this.fetchDataOptions = fetchDataOptions2;
|
this.fetchDataOptions = fetchDataOptions2;
|
||||||
}
|
}
|
||||||
askRelayerStatus(_0) {
|
askRelayerStatus(_0) {
|
||||||
@ -71463,76 +71570,48 @@ class RelayerClient {
|
|||||||
return status;
|
return status;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
filterRelayer(curr, relayer, subdomains, debugRelayer = false) {
|
filterRelayer(relayer) {
|
||||||
return __async(this, null, function* () {
|
return __async(this, null, function* () {
|
||||||
var _a;
|
var _a;
|
||||||
const { relayerEnsSubdomain } = this.config;
|
const hostname = relayer.hostnames[this.netId];
|
||||||
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;
|
|
||||||
const { ensName, relayerAddress } = relayer;
|
const { ensName, relayerAddress } = relayer;
|
||||||
const isOwner = !relayerAddress || relayerAddress === owner;
|
if (!hostname) {
|
||||||
const hasMinBalance = stakeBalance >= MIN_STAKE_BALANCE;
|
return;
|
||||||
const preCondition = hostname && isOwner && mainnetSubdomain && isRegistered && hasMinBalance && !isHostWithProtocol;
|
}
|
||||||
if (preCondition || debugRelayer) {
|
try {
|
||||||
try {
|
const status = yield this.askRelayerStatus({ hostname, relayerAddress });
|
||||||
const status = yield this.askRelayerStatus({ hostname, relayerAddress });
|
return {
|
||||||
return {
|
netId: status.netId,
|
||||||
netId: status.netId,
|
url: status.url,
|
||||||
url: status.url,
|
hostname,
|
||||||
hostname,
|
ensName,
|
||||||
ensName,
|
relayerAddress,
|
||||||
stakeBalance,
|
rewardAccount: (0,ethers__WEBPACK_IMPORTED_MODULE_5__/* .getAddress */ .b)(status.rewardAccount),
|
||||||
relayerAddress,
|
instances: getSupportedInstances(status.instances),
|
||||||
rewardAccount: (0,ethers__WEBPACK_IMPORTED_MODULE_5__/* .getAddress */ .b)(status.rewardAccount),
|
stakeBalance: relayer.stakeBalance,
|
||||||
instances: getSupportedInstances(status.instances),
|
gasPrice: (_a = status.gasPrices) == null ? void 0 : _a.fast,
|
||||||
gasPrice: (_a = status.gasPrices) == null ? void 0 : _a.fast,
|
ethPrices: status.ethPrices,
|
||||||
ethPrices: status.ethPrices,
|
currentQueue: status.currentQueue,
|
||||||
currentQueue: status.currentQueue,
|
tornadoServiceFee: status.tornadoServiceFee
|
||||||
tornadoServiceFee: status.tornadoServiceFee
|
};
|
||||||
};
|
} catch (err) {
|
||||||
} catch (err) {
|
|
||||||
if (debugRelayer) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
hostname,
|
|
||||||
relayerAddress,
|
|
||||||
errorMessage: err.message
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (debugRelayer) {
|
|
||||||
const errMsg = `Relayer ${hostname} condition not met`;
|
|
||||||
throw new Error(errMsg);
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
hostname,
|
hostname,
|
||||||
relayerAddress,
|
relayerAddress,
|
||||||
errorMessage: `Relayer ${hostname} condition not met`
|
errorMessage: err.message,
|
||||||
|
hasError: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
getValidRelayers(relayers, subdomains, debugRelayer = false) {
|
getValidRelayers(relayers) {
|
||||||
return __async(this, null, function* () {
|
return __async(this, null, function* () {
|
||||||
const relayersSet = /* @__PURE__ */ new Set();
|
|
||||||
const uniqueRelayers = relayers.reverse().filter(({ ensName }) => {
|
|
||||||
if (!relayersSet.has(ensName)) {
|
|
||||||
relayersSet.add(ensName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
const relayerNameHashes = uniqueRelayers.map((r) => (0,ethers__WEBPACK_IMPORTED_MODULE_6__/* .namehash */ .kM)(r.ensName));
|
|
||||||
const relayersData = yield this.Aggregator.relayersData.staticCall(relayerNameHashes, subdomains);
|
|
||||||
const invalidRelayers = [];
|
const invalidRelayers = [];
|
||||||
const validRelayers = (yield Promise.all(
|
const validRelayers = (yield Promise.all(relayers.map((relayer) => this.filterRelayer(relayer)))).filter((r) => {
|
||||||
relayersData.map((curr, index) => this.filterRelayer(curr, uniqueRelayers[index], subdomains, debugRelayer))
|
if (!r) {
|
||||||
)).filter((r) => {
|
return false;
|
||||||
if (r.errorMessage) {
|
}
|
||||||
|
if (r.hasError) {
|
||||||
invalidRelayers.push(r);
|
invalidRelayers.push(r);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -71545,7 +71624,7 @@ class RelayerClient {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
pickWeightedRandomRelayer(relayers) {
|
pickWeightedRandomRelayer(relayers) {
|
||||||
return pickWeightedRandomRelayer(relayers, this.netId);
|
return pickWeightedRandomRelayer(relayers);
|
||||||
}
|
}
|
||||||
tornadoWithdraw(_0) {
|
tornadoWithdraw(_0) {
|
||||||
return __async(this, arguments, function* ({ contract, proof, args }) {
|
return __async(this, arguments, function* ({ contract, proof, args }) {
|
||||||
@ -171078,11 +171157,12 @@ function encodeRlp(object) {
|
|||||||
|
|
||||||
// EXPORTS
|
// EXPORTS
|
||||||
__webpack_require__.d(__webpack_exports__, {
|
__webpack_require__.d(__webpack_exports__, {
|
||||||
|
ck: () => (/* binding */ formatEther),
|
||||||
g5: () => (/* binding */ parseEther),
|
g5: () => (/* binding */ parseEther),
|
||||||
XS: () => (/* binding */ parseUnits)
|
XS: () => (/* binding */ parseUnits)
|
||||||
});
|
});
|
||||||
|
|
||||||
// UNUSED EXPORTS: formatEther, formatUnits
|
// UNUSED EXPORTS: formatUnits
|
||||||
|
|
||||||
// EXTERNAL MODULE: ./node_modules/ethers/lib.esm/utils/errors.js
|
// EXTERNAL MODULE: ./node_modules/ethers/lib.esm/utils/errors.js
|
||||||
var errors = __webpack_require__(57339);
|
var errors = __webpack_require__(57339);
|
||||||
@ -171253,7 +171333,7 @@ function fixednumber_toString(val, decimals) {
|
|||||||
* variant will silently ignore underflow, while the //signalling// variant
|
* variant will silently ignore underflow, while the //signalling// variant
|
||||||
* will thow a [[NumericFaultError]] on underflow.
|
* will thow a [[NumericFaultError]] on underflow.
|
||||||
*/
|
*/
|
||||||
class fixednumber_FixedNumber {
|
class FixedNumber {
|
||||||
/**
|
/**
|
||||||
* The specific fixed-point arithmetic field for this value.
|
* The specific fixed-point arithmetic field for this value.
|
||||||
*/
|
*/
|
||||||
@ -171328,7 +171408,7 @@ class fixednumber_FixedNumber {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
val = checkValue(val, this.#format, safeOp);
|
val = checkValue(val, this.#format, safeOp);
|
||||||
return new fixednumber_FixedNumber(_guard, val, this.#format);
|
return new FixedNumber(_guard, val, this.#format);
|
||||||
}
|
}
|
||||||
#add(o, safeOp) {
|
#add(o, safeOp) {
|
||||||
this.#checkFormat(o);
|
this.#checkFormat(o);
|
||||||
@ -171515,7 +171595,7 @@ class fixednumber_FixedNumber {
|
|||||||
const tens = getTens(delta);
|
const tens = getTens(delta);
|
||||||
value = (value / tens) * tens;
|
value = (value / tens) * tens;
|
||||||
checkValue(value, this.#format, "round");
|
checkValue(value, this.#format, "round");
|
||||||
return new fixednumber_FixedNumber(_guard, value, this.#format);
|
return new FixedNumber(_guard, value, this.#format);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Returns true if %%this%% is equal to ``0``.
|
* Returns true if %%this%% is equal to ``0``.
|
||||||
@ -171544,7 +171624,7 @@ class fixednumber_FixedNumber {
|
|||||||
* This will throw if the value cannot fit into %%format%%.
|
* This will throw if the value cannot fit into %%format%%.
|
||||||
*/
|
*/
|
||||||
toFormat(format) {
|
toFormat(format) {
|
||||||
return fixednumber_FixedNumber.fromString(this.toString(), format);
|
return FixedNumber.fromString(this.toString(), format);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Creates a new [[FixedNumber]] for %%value%% divided by
|
* Creates a new [[FixedNumber]] for %%value%% divided by
|
||||||
@ -171570,7 +171650,7 @@ class fixednumber_FixedNumber {
|
|||||||
value *= getTens(-delta);
|
value *= getTens(-delta);
|
||||||
}
|
}
|
||||||
checkValue(value, format, "fromValue");
|
checkValue(value, format, "fromValue");
|
||||||
return new fixednumber_FixedNumber(_guard, value, format);
|
return new FixedNumber(_guard, value, format);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Creates a new [[FixedNumber]] for %%value%% with %%format%%.
|
* Creates a new [[FixedNumber]] for %%value%% with %%format%%.
|
||||||
@ -171595,7 +171675,7 @@ class fixednumber_FixedNumber {
|
|||||||
decimal = decimal.substring(0, format.decimals);
|
decimal = decimal.substring(0, format.decimals);
|
||||||
const value = BigInt(match[1] + whole + decimal);
|
const value = BigInt(match[1] + whole + decimal);
|
||||||
checkValue(value, format, "fromString");
|
checkValue(value, format, "fromString");
|
||||||
return new fixednumber_FixedNumber(_guard, value, format);
|
return new FixedNumber(_guard, value, format);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Creates a new [[FixedNumber]] with the big-endian representation
|
* Creates a new [[FixedNumber]] with the big-endian representation
|
||||||
@ -171611,7 +171691,7 @@ class fixednumber_FixedNumber {
|
|||||||
value = (0,maths/* fromTwos */.ST)(value, format.width);
|
value = (0,maths/* fromTwos */.ST)(value, format.width);
|
||||||
}
|
}
|
||||||
checkValue(value, format, "fromBytes");
|
checkValue(value, format, "fromBytes");
|
||||||
return new fixednumber_FixedNumber(_guard, value, format);
|
return new FixedNumber(_guard, value, format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//const f1 = FixedNumber.fromString("12.56", "fixed16x2");
|
//const f1 = FixedNumber.fromString("12.56", "fixed16x2");
|
||||||
@ -171663,11 +171743,11 @@ function formatUnits(value, unit) {
|
|||||||
let decimals = 18;
|
let decimals = 18;
|
||||||
if (typeof (unit) === "string") {
|
if (typeof (unit) === "string") {
|
||||||
const index = names.indexOf(unit);
|
const index = names.indexOf(unit);
|
||||||
assertArgument(index >= 0, "invalid unit", "unit", unit);
|
(0,errors/* assertArgument */.MR)(index >= 0, "invalid unit", "unit", unit);
|
||||||
decimals = 3 * index;
|
decimals = 3 * index;
|
||||||
}
|
}
|
||||||
else if (unit != null) {
|
else if (unit != null) {
|
||||||
decimals = getNumber(unit, "unit");
|
decimals = (0,maths/* getNumber */.WZ)(unit, "unit");
|
||||||
}
|
}
|
||||||
return FixedNumber.fromValue(value, decimals, { decimals, width: 512 }).toString();
|
return FixedNumber.fromValue(value, decimals, { decimals, width: 512 }).toString();
|
||||||
}
|
}
|
||||||
@ -171687,7 +171767,7 @@ function parseUnits(value, unit) {
|
|||||||
else if (unit != null) {
|
else if (unit != null) {
|
||||||
decimals = (0,maths/* getNumber */.WZ)(unit, "unit");
|
decimals = (0,maths/* getNumber */.WZ)(unit, "unit");
|
||||||
}
|
}
|
||||||
return fixednumber_FixedNumber.fromString(value, { decimals, width: 512 }).value;
|
return FixedNumber.fromString(value, { decimals, width: 512 }).value;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Converts %%value%% into a //decimal string// using 18 decimal places.
|
* Converts %%value%% into a //decimal string// using 18 decimal places.
|
||||||
@ -172891,6 +172971,8 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
/* harmony export */ GET_STATISTIC: () => (/* reexport safe */ _graphql__WEBPACK_IMPORTED_MODULE_1__.GET_STATISTIC),
|
/* harmony export */ GET_STATISTIC: () => (/* reexport safe */ _graphql__WEBPACK_IMPORTED_MODULE_1__.GET_STATISTIC),
|
||||||
/* harmony export */ GET_WITHDRAWALS: () => (/* reexport safe */ _graphql__WEBPACK_IMPORTED_MODULE_1__.GET_WITHDRAWALS),
|
/* harmony export */ GET_WITHDRAWALS: () => (/* reexport safe */ _graphql__WEBPACK_IMPORTED_MODULE_1__.GET_WITHDRAWALS),
|
||||||
/* harmony export */ Invoice: () => (/* reexport safe */ _deposits__WEBPACK_IMPORTED_MODULE_5__.qO),
|
/* harmony export */ Invoice: () => (/* reexport safe */ _deposits__WEBPACK_IMPORTED_MODULE_5__.qO),
|
||||||
|
/* harmony export */ MAX_FEE: () => (/* reexport safe */ _relayerClient__WEBPACK_IMPORTED_MODULE_15__.KN),
|
||||||
|
/* harmony export */ MIN_FEE: () => (/* reexport safe */ _relayerClient__WEBPACK_IMPORTED_MODULE_15__.Ss),
|
||||||
/* harmony export */ MIN_STAKE_BALANCE: () => (/* reexport safe */ _relayerClient__WEBPACK_IMPORTED_MODULE_15__.pO),
|
/* harmony export */ MIN_STAKE_BALANCE: () => (/* reexport safe */ _relayerClient__WEBPACK_IMPORTED_MODULE_15__.pO),
|
||||||
/* harmony export */ MerkleTreeService: () => (/* reexport safe */ _merkleTree__WEBPACK_IMPORTED_MODULE_8__.s),
|
/* harmony export */ MerkleTreeService: () => (/* reexport safe */ _merkleTree__WEBPACK_IMPORTED_MODULE_8__.s),
|
||||||
/* harmony export */ Mimc: () => (/* reexport safe */ _mimc__WEBPACK_IMPORTED_MODULE_9__.p),
|
/* harmony export */ Mimc: () => (/* reexport safe */ _mimc__WEBPACK_IMPORTED_MODULE_9__.p),
|
||||||
@ -172953,6 +173035,7 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
/* harmony export */ getProvider: () => (/* reexport safe */ _providers__WEBPACK_IMPORTED_MODULE_14__.sO),
|
/* harmony export */ getProvider: () => (/* reexport safe */ _providers__WEBPACK_IMPORTED_MODULE_14__.sO),
|
||||||
/* harmony export */ getProviderWithNetId: () => (/* reexport safe */ _providers__WEBPACK_IMPORTED_MODULE_14__.MF),
|
/* harmony export */ getProviderWithNetId: () => (/* reexport safe */ _providers__WEBPACK_IMPORTED_MODULE_14__.MF),
|
||||||
/* harmony export */ getRegisters: () => (/* reexport safe */ _graphql__WEBPACK_IMPORTED_MODULE_1__.getRegisters),
|
/* harmony export */ getRegisters: () => (/* reexport safe */ _graphql__WEBPACK_IMPORTED_MODULE_1__.getRegisters),
|
||||||
|
/* harmony export */ getRelayerEnsSubdomains: () => (/* reexport safe */ _networkConfig__WEBPACK_IMPORTED_MODULE_11__.o2),
|
||||||
/* harmony export */ getStatistic: () => (/* reexport safe */ _graphql__WEBPACK_IMPORTED_MODULE_1__.getStatistic),
|
/* harmony export */ getStatistic: () => (/* reexport safe */ _graphql__WEBPACK_IMPORTED_MODULE_1__.getStatistic),
|
||||||
/* harmony export */ getStatusSchema: () => (/* reexport safe */ _schemas__WEBPACK_IMPORTED_MODULE_2__.c_),
|
/* harmony export */ getStatusSchema: () => (/* reexport safe */ _schemas__WEBPACK_IMPORTED_MODULE_2__.c_),
|
||||||
/* harmony export */ getSubdomains: () => (/* reexport safe */ _networkConfig__WEBPACK_IMPORTED_MODULE_11__.cF),
|
/* harmony export */ getSubdomains: () => (/* reexport safe */ _networkConfig__WEBPACK_IMPORTED_MODULE_11__.cF),
|
||||||
|
4
dist/networkConfig.d.ts
vendored
4
dist/networkConfig.d.ts
vendored
@ -87,6 +87,9 @@ export type Config = {
|
|||||||
export type networkConfig = {
|
export type networkConfig = {
|
||||||
[key in NetIdType]: Config;
|
[key in NetIdType]: Config;
|
||||||
};
|
};
|
||||||
|
export type SubdomainMap = {
|
||||||
|
[key in NetIdType]: string;
|
||||||
|
};
|
||||||
export declare const defaultConfig: networkConfig;
|
export declare const defaultConfig: networkConfig;
|
||||||
export declare const enabledChains: NetIdType[];
|
export declare const enabledChains: NetIdType[];
|
||||||
/**
|
/**
|
||||||
@ -112,3 +115,4 @@ export declare function getInstanceByAddress({ netId, address }: {
|
|||||||
currency: string;
|
currency: string;
|
||||||
} | undefined;
|
} | undefined;
|
||||||
export declare function getSubdomains(): string[];
|
export declare function getSubdomains(): string[];
|
||||||
|
export declare function getRelayerEnsSubdomains(): SubdomainMap;
|
||||||
|
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 { NetIdType, Config } from './networkConfig';
|
||||||
import { fetchDataOptions } from './providers';
|
import { fetchDataOptions } from './providers';
|
||||||
import type { snarkProofs } from './websnark';
|
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 declare const MIN_STAKE_BALANCE: bigint;
|
||||||
export interface RelayerParams {
|
export interface RelayerParams {
|
||||||
ensName: string;
|
ensName: string;
|
||||||
relayerAddress?: string;
|
relayerAddress: string;
|
||||||
}
|
}
|
||||||
export interface Relayer {
|
/**
|
||||||
|
* Info from relayer status
|
||||||
|
*/
|
||||||
|
export type RelayerInfo = RelayerParams & {
|
||||||
netId: NetIdType;
|
netId: NetIdType;
|
||||||
url: string;
|
url: string;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
rewardAccount: string;
|
rewardAccount: string;
|
||||||
instances: string[];
|
instances: string[];
|
||||||
|
stakeBalance?: string;
|
||||||
gasPrice?: number;
|
gasPrice?: number;
|
||||||
ethPrices?: {
|
ethPrices?: {
|
||||||
[key in string]: string;
|
[key in string]: string;
|
||||||
};
|
};
|
||||||
currentQueue: number;
|
currentQueue: number;
|
||||||
tornadoServiceFee: number;
|
tornadoServiceFee: number;
|
||||||
}
|
|
||||||
export type RelayerInfo = Relayer & {
|
|
||||||
ensName: string;
|
|
||||||
stakeBalance: bigint;
|
|
||||||
relayerAddress: string;
|
|
||||||
};
|
};
|
||||||
export type RelayerError = {
|
export type RelayerError = {
|
||||||
hostname: string;
|
hostname: string;
|
||||||
relayerAddress?: string;
|
relayerAddress?: string;
|
||||||
errorMessage?: string;
|
errorMessage?: string;
|
||||||
|
hasError: boolean;
|
||||||
};
|
};
|
||||||
export interface RelayerStatus {
|
export interface RelayerStatus {
|
||||||
url: string;
|
url: string;
|
||||||
@ -87,7 +88,7 @@ export interface semanticVersion {
|
|||||||
}
|
}
|
||||||
export declare function parseSemanticVersion(version: string): semanticVersion;
|
export declare function parseSemanticVersion(version: string): semanticVersion;
|
||||||
export declare function isRelayerUpdated(relayerVersion: string, netId: NetIdType): boolean;
|
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 declare function getWeightRandom(weightsScores: bigint[], random: bigint): number;
|
||||||
export type RelayerInstanceList = {
|
export type RelayerInstanceList = {
|
||||||
[key in string]: {
|
[key in string]: {
|
||||||
@ -97,11 +98,10 @@ export type RelayerInstanceList = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
export declare function getSupportedInstances(instanceList: RelayerInstanceList): string[];
|
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 {
|
export interface RelayerClientConstructor {
|
||||||
netId: NetIdType;
|
netId: NetIdType;
|
||||||
config: Config;
|
config: Config;
|
||||||
Aggregator: Aggregator;
|
|
||||||
fetchDataOptions?: fetchDataOptions;
|
fetchDataOptions?: fetchDataOptions;
|
||||||
}
|
}
|
||||||
export type RelayerClientWithdraw = snarkProofs & {
|
export type RelayerClientWithdraw = snarkProofs & {
|
||||||
@ -110,16 +110,15 @@ export type RelayerClientWithdraw = snarkProofs & {
|
|||||||
export declare class RelayerClient {
|
export declare class RelayerClient {
|
||||||
netId: NetIdType;
|
netId: NetIdType;
|
||||||
config: Config;
|
config: Config;
|
||||||
Aggregator: Aggregator;
|
selectedRelayer?: RelayerInfo;
|
||||||
selectedRelayer?: Relayer;
|
|
||||||
fetchDataOptions?: fetchDataOptions;
|
fetchDataOptions?: fetchDataOptions;
|
||||||
constructor({ netId, config, Aggregator, fetchDataOptions }: RelayerClientConstructor);
|
constructor({ netId, config, fetchDataOptions }: RelayerClientConstructor);
|
||||||
askRelayerStatus({ hostname, relayerAddress, }: {
|
askRelayerStatus({ hostname, relayerAddress, }: {
|
||||||
hostname: string;
|
hostname: string;
|
||||||
relayerAddress?: string;
|
relayerAddress?: string;
|
||||||
}): Promise<RelayerStatus>;
|
}): Promise<RelayerStatus>;
|
||||||
filterRelayer(curr: RelayerStructOutput, relayer: RelayerParams, subdomains: string[], debugRelayer?: boolean): Promise<RelayerInfo | RelayerError>;
|
filterRelayer(relayer: CachedRelayerInfo): Promise<RelayerInfo | RelayerError | undefined>;
|
||||||
getValidRelayers(relayers: RelayerParams[], subdomains: string[], debugRelayer?: boolean): Promise<{
|
getValidRelayers(relayers: CachedRelayerInfo[]): Promise<{
|
||||||
validRelayers: RelayerInfo[];
|
validRelayers: RelayerInfo[];
|
||||||
invalidRelayers: RelayerError[];
|
invalidRelayers: RelayerError[];
|
||||||
}>;
|
}>;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@tornado/core",
|
"name": "@tornado/core",
|
||||||
"version": "1.0.4",
|
"version": "1.0.5",
|
||||||
"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",
|
||||||
|
@ -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 {
|
import type {
|
||||||
Tornado,
|
Tornado,
|
||||||
TornadoRouter,
|
TornadoRouter,
|
||||||
@ -6,8 +17,11 @@ import type {
|
|||||||
Governance,
|
Governance,
|
||||||
RelayerRegistry,
|
RelayerRegistry,
|
||||||
Echoer,
|
Echoer,
|
||||||
|
Aggregator,
|
||||||
} from '@tornado/contracts';
|
} from '@tornado/contracts';
|
||||||
|
|
||||||
import * as graph from '../graphql';
|
import * as graph from '../graphql';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BatchEventsService,
|
BatchEventsService,
|
||||||
BatchBlockService,
|
BatchBlockService,
|
||||||
@ -15,8 +29,11 @@ import {
|
|||||||
BatchEventOnProgress,
|
BatchEventOnProgress,
|
||||||
BatchBlockOnProgress,
|
BatchBlockOnProgress,
|
||||||
} from '../batch';
|
} from '../batch';
|
||||||
import { fetchDataOptions } from '../providers';
|
|
||||||
import type { NetIdType } from '../networkConfig';
|
import type { fetchDataOptions } from '../providers';
|
||||||
|
import type { NetIdType, Config, SubdomainMap } from '../networkConfig';
|
||||||
|
import { RelayerParams, MIN_STAKE_BALANCE } from '../relayerClient';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
BaseEvents,
|
BaseEvents,
|
||||||
CachedEvents,
|
CachedEvents,
|
||||||
@ -741,27 +758,57 @@ 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[];
|
||||||
|
}
|
||||||
|
|
||||||
export type BaseRegistryServiceConstructor = {
|
export type BaseRegistryServiceConstructor = {
|
||||||
netId: NetIdType;
|
netId: NetIdType;
|
||||||
provider: Provider;
|
provider: Provider;
|
||||||
graphApi?: string;
|
graphApi?: string;
|
||||||
subgraphName?: string;
|
subgraphName?: string;
|
||||||
RelayerRegistry: RelayerRegistry;
|
RelayerRegistry: RelayerRegistry;
|
||||||
|
Aggregator: Aggregator;
|
||||||
|
relayerEnsSubdomains: SubdomainMap;
|
||||||
deployedBlock?: number;
|
deployedBlock?: number;
|
||||||
fetchDataOptions?: fetchDataOptions;
|
fetchDataOptions?: fetchDataOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class BaseRegistryService extends BaseEventsService<RegistersEvents> {
|
export class BaseRegistryService extends BaseEventsService<RegistersEvents> {
|
||||||
|
Aggregator: Aggregator;
|
||||||
|
relayerEnsSubdomains: SubdomainMap;
|
||||||
|
updateInterval: number;
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
netId,
|
netId,
|
||||||
provider,
|
provider,
|
||||||
graphApi,
|
graphApi,
|
||||||
subgraphName,
|
subgraphName,
|
||||||
RelayerRegistry,
|
RelayerRegistry,
|
||||||
|
Aggregator,
|
||||||
|
relayerEnsSubdomains,
|
||||||
deployedBlock,
|
deployedBlock,
|
||||||
fetchDataOptions,
|
fetchDataOptions,
|
||||||
}: BaseRegistryServiceConstructor) {
|
}: BaseRegistryServiceConstructor) {
|
||||||
super({ netId, provider, graphApi, subgraphName, contract: RelayerRegistry, deployedBlock, fetchDataOptions });
|
super({ netId, provider, graphApi, subgraphName, contract: RelayerRegistry, deployedBlock, fetchDataOptions });
|
||||||
|
|
||||||
|
this.Aggregator = Aggregator;
|
||||||
|
this.relayerEnsSubdomains = relayerEnsSubdomains;
|
||||||
|
|
||||||
|
this.updateInterval = 86400;
|
||||||
}
|
}
|
||||||
|
|
||||||
getInstanceName() {
|
getInstanceName() {
|
||||||
@ -794,7 +841,114 @@ 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: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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> {
|
||||||
|
let { timestamp, relayers } = await this.getSavedRelayers();
|
||||||
|
|
||||||
|
if (!relayers.length || timestamp + this.updateInterval < Math.floor(Date.now() / 1000)) {
|
||||||
|
console.log('\nUpdating relayers from registry\n');
|
||||||
|
|
||||||
|
({ timestamp, relayers } = await this.getLatestRelayers());
|
||||||
|
|
||||||
|
await this.saveRelayers({ timestamp, relayers });
|
||||||
|
}
|
||||||
|
|
||||||
|
return { timestamp, relayers };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,10 @@ export type networkConfig = {
|
|||||||
[key in NetIdType]: Config;
|
[key in NetIdType]: Config;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type SubdomainMap = {
|
||||||
|
[key in NetIdType]: string;
|
||||||
|
};
|
||||||
|
|
||||||
export const defaultConfig: networkConfig = {
|
export const defaultConfig: networkConfig = {
|
||||||
[NetId.MAINNET]: {
|
[NetId.MAINNET]: {
|
||||||
rpcCallRetryAttempt: 15,
|
rpcCallRetryAttempt: 15,
|
||||||
@ -611,10 +615,6 @@ export const defaultConfig: networkConfig = {
|
|||||||
tornadoSubgraph: 'tornadocash/sepolia-tornado-subgraph',
|
tornadoSubgraph: 'tornadocash/sepolia-tornado-subgraph',
|
||||||
subgraphs: {},
|
subgraphs: {},
|
||||||
rpcUrls: {
|
rpcUrls: {
|
||||||
pandaops: {
|
|
||||||
name: 'ethpandaops',
|
|
||||||
url: 'https://rpc.sepolia.ethpandaops.io',
|
|
||||||
},
|
|
||||||
sepolia: {
|
sepolia: {
|
||||||
name: 'Sepolia RPC',
|
name: 'Sepolia RPC',
|
||||||
url: 'https://rpc.sepolia.org',
|
url: 'https://rpc.sepolia.org',
|
||||||
@ -627,6 +627,10 @@ export const defaultConfig: networkConfig = {
|
|||||||
name: '1rpc',
|
name: '1rpc',
|
||||||
url: 'https://1rpc.io/sepolia',
|
url: 'https://1rpc.io/sepolia',
|
||||||
},
|
},
|
||||||
|
ethpandaops: {
|
||||||
|
name: 'ethpandaops',
|
||||||
|
url: 'https://rpc.sepolia.ethpandaops.io',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
tokens: {
|
tokens: {
|
||||||
eth: {
|
eth: {
|
||||||
@ -738,3 +742,12 @@ export function getSubdomains() {
|
|||||||
|
|
||||||
return enabledChains.map((chain) => allConfig[chain].relayerEnsSubdomain);
|
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);
|
||||||
|
}
|
||||||
|
@ -1,43 +1,45 @@
|
|||||||
import { getAddress, namehash, parseEther } from 'ethers';
|
import { getAddress, parseEther } from 'ethers';
|
||||||
import type { Aggregator } from '@tornado/contracts';
|
|
||||||
import type { RelayerStructOutput } from '@tornado/contracts/dist/contracts/Governance/Aggregator/Aggregator';
|
|
||||||
import { sleep } from './utils';
|
import { sleep } from './utils';
|
||||||
import { NetId, NetIdType, Config } from './networkConfig';
|
import { NetId, NetIdType, Config } from './networkConfig';
|
||||||
import { fetchData, fetchDataOptions } from './providers';
|
import { fetchData, fetchDataOptions } from './providers';
|
||||||
import { ajv, jobsSchema, getStatusSchema } from './schemas';
|
import { ajv, jobsSchema, getStatusSchema } from './schemas';
|
||||||
import type { snarkProofs } from './websnark';
|
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 const MIN_STAKE_BALANCE = parseEther('500');
|
||||||
|
|
||||||
export interface RelayerParams {
|
export interface RelayerParams {
|
||||||
ensName: string;
|
ensName: string;
|
||||||
relayerAddress?: string;
|
relayerAddress: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Relayer {
|
/**
|
||||||
|
* Info from relayer status
|
||||||
|
*/
|
||||||
|
export type RelayerInfo = RelayerParams & {
|
||||||
netId: NetIdType;
|
netId: NetIdType;
|
||||||
url: string;
|
url: string;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
rewardAccount: string;
|
rewardAccount: string;
|
||||||
instances: string[];
|
instances: string[];
|
||||||
|
stakeBalance?: string;
|
||||||
gasPrice?: number;
|
gasPrice?: number;
|
||||||
ethPrices?: {
|
ethPrices?: {
|
||||||
[key in string]: string;
|
[key in string]: string;
|
||||||
};
|
};
|
||||||
currentQueue: number;
|
currentQueue: number;
|
||||||
tornadoServiceFee: number;
|
tornadoServiceFee: number;
|
||||||
}
|
|
||||||
|
|
||||||
export type RelayerInfo = Relayer & {
|
|
||||||
ensName: string;
|
|
||||||
stakeBalance: bigint;
|
|
||||||
relayerAddress: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RelayerError = {
|
export type RelayerError = {
|
||||||
hostname: string;
|
hostname: string;
|
||||||
relayerAddress?: string;
|
relayerAddress?: string;
|
||||||
errorMessage?: string;
|
errorMessage?: string;
|
||||||
|
hasError: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface RelayerStatus {
|
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
|
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) {
|
export function calculateScore({ stakeBalance, tornadoServiceFee }: RelayerInfo) {
|
||||||
if (tornadoServiceFee < minFee) {
|
if (tornadoServiceFee < MIN_FEE) {
|
||||||
tornadoServiceFee = minFee;
|
tornadoServiceFee = MIN_FEE;
|
||||||
} else if (tornadoServiceFee >= maxFee) {
|
} else if (tornadoServiceFee >= MAX_FEE) {
|
||||||
return BigInt(0);
|
return BigInt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const serviceFeeCoefficient = (tornadoServiceFee - minFee) ** 2;
|
const serviceFeeCoefficient = (tornadoServiceFee - MIN_FEE) ** 2;
|
||||||
const feeDiffCoefficient = 1 / (maxFee - minFee) ** 2;
|
const feeDiffCoefficient = 1 / (MAX_FEE - MIN_FEE) ** 2;
|
||||||
const coefficientsMultiplier = 1 - feeDiffCoefficient * serviceFeeCoefficient;
|
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) {
|
export function getWeightRandom(weightsScores: bigint[], random: bigint) {
|
||||||
@ -159,20 +161,13 @@ export function getSupportedInstances(instanceList: RelayerInstanceList) {
|
|||||||
return rawList.map((l) => getAddress(l));
|
return rawList.map((l) => getAddress(l));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pickWeightedRandomRelayer(relayers: RelayerInfo[], netId: NetIdType) {
|
export function pickWeightedRandomRelayer(relayers: RelayerInfo[]) {
|
||||||
let minFee: number, maxFee: number;
|
const weightsScores = relayers.map((el) => calculateScore(el));
|
||||||
|
|
||||||
if (netId !== NetId.MAINNET) {
|
|
||||||
minFee = 0.01;
|
|
||||||
maxFee = 0.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
const weightsScores = relayers.map((el) => calculateScore(el, minFee, maxFee));
|
|
||||||
const totalWeight = weightsScores.reduce((acc, curr) => {
|
const totalWeight = weightsScores.reduce((acc, curr) => {
|
||||||
return (acc = acc + curr);
|
return (acc = acc + curr);
|
||||||
}, BigInt('0'));
|
}, BigInt('0'));
|
||||||
|
|
||||||
const random = BigInt(Number(totalWeight) * Math.random());
|
const random = BigInt(Math.floor(Number(totalWeight) * Math.random()));
|
||||||
const weightRandomIndex = getWeightRandom(weightsScores, random);
|
const weightRandomIndex = getWeightRandom(weightsScores, random);
|
||||||
|
|
||||||
return relayers[weightRandomIndex];
|
return relayers[weightRandomIndex];
|
||||||
@ -181,7 +176,6 @@ export function pickWeightedRandomRelayer(relayers: RelayerInfo[], netId: NetIdT
|
|||||||
export interface RelayerClientConstructor {
|
export interface RelayerClientConstructor {
|
||||||
netId: NetIdType;
|
netId: NetIdType;
|
||||||
config: Config;
|
config: Config;
|
||||||
Aggregator: Aggregator;
|
|
||||||
fetchDataOptions?: fetchDataOptions;
|
fetchDataOptions?: fetchDataOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,14 +186,12 @@ export type RelayerClientWithdraw = snarkProofs & {
|
|||||||
export class RelayerClient {
|
export class RelayerClient {
|
||||||
netId: NetIdType;
|
netId: NetIdType;
|
||||||
config: Config;
|
config: Config;
|
||||||
Aggregator: Aggregator;
|
selectedRelayer?: RelayerInfo;
|
||||||
selectedRelayer?: Relayer;
|
|
||||||
fetchDataOptions?: fetchDataOptions;
|
fetchDataOptions?: fetchDataOptions;
|
||||||
|
|
||||||
constructor({ netId, config, Aggregator, fetchDataOptions }: RelayerClientConstructor) {
|
constructor({ netId, config, fetchDataOptions }: RelayerClientConstructor) {
|
||||||
this.netId = netId;
|
this.netId = netId;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.Aggregator = Aggregator;
|
|
||||||
this.fetchDataOptions = fetchDataOptions;
|
this.fetchDataOptions = fetchDataOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,101 +243,54 @@ export class RelayerClient {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
async filterRelayer(
|
async filterRelayer(relayer: CachedRelayerInfo): Promise<RelayerInfo | RelayerError | undefined> {
|
||||||
curr: RelayerStructOutput,
|
const hostname = relayer.hostnames[this.netId];
|
||||||
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;
|
|
||||||
const { ensName, relayerAddress } = relayer;
|
const { ensName, relayerAddress } = relayer;
|
||||||
|
|
||||||
const isOwner = !relayerAddress || relayerAddress === owner;
|
if (!hostname) {
|
||||||
const hasMinBalance = stakeBalance >= MIN_STAKE_BALANCE;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const preCondition =
|
try {
|
||||||
hostname && isOwner && mainnetSubdomain && isRegistered && hasMinBalance && !isHostWithProtocol;
|
const status = await this.askRelayerStatus({ hostname, relayerAddress });
|
||||||
|
|
||||||
if (preCondition || debugRelayer) {
|
return {
|
||||||
try {
|
netId: status.netId,
|
||||||
const status = await this.askRelayerStatus({ hostname, relayerAddress });
|
url: status.url,
|
||||||
|
hostname,
|
||||||
return {
|
ensName,
|
||||||
netId: status.netId,
|
relayerAddress,
|
||||||
url: status.url,
|
rewardAccount: getAddress(status.rewardAccount),
|
||||||
hostname,
|
instances: getSupportedInstances(status.instances),
|
||||||
ensName,
|
stakeBalance: relayer.stakeBalance,
|
||||||
stakeBalance,
|
gasPrice: status.gasPrices?.fast,
|
||||||
relayerAddress,
|
ethPrices: status.ethPrices,
|
||||||
rewardAccount: getAddress(status.rewardAccount),
|
currentQueue: status.currentQueue,
|
||||||
instances: getSupportedInstances(status.instances),
|
tornadoServiceFee: status.tornadoServiceFee,
|
||||||
gasPrice: status.gasPrices?.fast,
|
} as RelayerInfo;
|
||||||
ethPrices: status.ethPrices,
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
currentQueue: status.currentQueue,
|
} catch (err: any) {
|
||||||
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 {
|
return {
|
||||||
hostname,
|
hostname,
|
||||||
relayerAddress,
|
relayerAddress,
|
||||||
errorMessage: `Relayer ${hostname} condition not met`,
|
errorMessage: err.message,
|
||||||
};
|
hasError: true,
|
||||||
|
} as RelayerError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getValidRelayers(
|
async getValidRelayers(relayers: CachedRelayerInfo[]): Promise<{
|
||||||
// this should be ascending order of events
|
|
||||||
relayers: RelayerParams[],
|
|
||||||
subdomains: string[],
|
|
||||||
debugRelayer: boolean = false,
|
|
||||||
): Promise<{
|
|
||||||
validRelayers: RelayerInfo[];
|
validRelayers: RelayerInfo[];
|
||||||
invalidRelayers: RelayerError[];
|
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 invalidRelayers: RelayerError[] = [];
|
||||||
|
|
||||||
const validRelayers = (
|
const validRelayers = (await Promise.all(relayers.map((relayer) => this.filterRelayer(relayer)))).filter((r) => {
|
||||||
await Promise.all(
|
if (!r) {
|
||||||
relayersData.map((curr, index) => this.filterRelayer(curr, uniqueRelayers[index], subdomains, debugRelayer)),
|
return false;
|
||||||
)
|
}
|
||||||
).filter((r) => {
|
if ((r as RelayerError).hasError) {
|
||||||
if ((r as RelayerError).errorMessage) {
|
invalidRelayers.push(r as RelayerError);
|
||||||
invalidRelayers.push(r);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -358,11 +303,11 @@ export class RelayerClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pickWeightedRandomRelayer(relayers: RelayerInfo[]) {
|
pickWeightedRandomRelayer(relayers: RelayerInfo[]) {
|
||||||
return pickWeightedRandomRelayer(relayers, this.netId);
|
return pickWeightedRandomRelayer(relayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
async tornadoWithdraw({ contract, proof, args }: RelayerClientWithdraw) {
|
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`, {
|
const withdrawResponse = (await fetchData(`${url}v1/tornadoWithdraw`, {
|
||||||
...this.fetchDataOptions,
|
...this.fetchDataOptions,
|
||||||
|
Loading…
Reference in New Issue
Block a user