tornado-core/dist/index.js
tornadocontrib 82aeabd739
Allow custom URL format relayers
should be convenient  to test locally
2024-09-27 04:56:19 +00:00

6804 lines
181 KiB
JavaScript
Vendored

'use strict';
var ethers = require('ethers');
var crossFetch = require('cross-fetch');
var crypto$1 = require('crypto');
var BN = require('bn.js');
var Ajv = require('ajv');
var circomlibjs = require('circomlibjs');
var ethSigUtil = require('@metamask/eth-sig-util');
var worker_threads = require('worker_threads');
var fixedMerkleTree = require('@tornado/fixed-merkle-tree');
var websnarkUtils = require('@tornado/websnark/src/utils');
var websnarkGroth = require('@tornado/websnark/src/groth16');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var websnarkUtils__namespace = /*#__PURE__*/_interopNamespaceDefault(websnarkUtils);
var __async$d = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
BigInt.prototype.toJSON = function() {
return this.toString();
};
const isNode = !process.browser && typeof globalThis.window === "undefined";
const crypto = isNode ? crypto$1.webcrypto : globalThis.crypto;
const chunk = (arr, size) => [...Array(Math.ceil(arr.length / size))].map((_, i) => arr.slice(size * i, size + size * i));
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function validateUrl(url, protocols) {
try {
const parsedUrl = new URL(url);
if (protocols && protocols.length) {
return protocols.map((p) => p.toLowerCase()).includes(parsedUrl.protocol);
}
return true;
} catch (e) {
return false;
}
}
function concatBytes(...arrays) {
const totalSize = arrays.reduce((acc, e) => acc + e.length, 0);
const merged = new Uint8Array(totalSize);
arrays.forEach((array, i, arrays2) => {
const offset = arrays2.slice(0, i).reduce((acc, e) => acc + e.length, 0);
merged.set(array, offset);
});
return merged;
}
function bufferToBytes(b) {
return new Uint8Array(b.buffer);
}
function bytesToBase64(bytes) {
return btoa(bytes.reduce((data, byte) => data + String.fromCharCode(byte), ""));
}
function base64ToBytes(base64) {
return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
}
function bytesToHex(bytes) {
return "0x" + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
}
function hexToBytes(hexString) {
if (hexString.slice(0, 2) === "0x") {
hexString = hexString.replace("0x", "");
}
if (hexString.length % 2 !== 0) {
hexString = "0" + hexString;
}
return Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
}
function bytesToBN(bytes) {
return BigInt(bytesToHex(bytes));
}
function bnToBytes(bigint) {
let hexString = typeof bigint === "bigint" ? bigint.toString(16) : bigint;
if (hexString.startsWith("0x")) {
hexString = hexString.replace("0x", "");
}
if (hexString.length % 2 !== 0) {
hexString = "0" + hexString;
}
return Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
}
function leBuff2Int(bytes) {
return new BN(bytes, 16, "le");
}
function leInt2Buff(bigint) {
return Uint8Array.from(new BN(bigint).toArray("le", 31));
}
function toFixedHex(numberish, length = 32) {
return "0x" + BigInt(numberish).toString(16).padStart(length * 2, "0");
}
function toFixedLength(string, length = 32) {
string = string.replace("0x", "");
return "0x" + string.padStart(length * 2, "0");
}
function rBigInt(nbytes = 31) {
return bytesToBN(crypto.getRandomValues(new Uint8Array(nbytes)));
}
function bigIntReplacer(key, value) {
return typeof value === "bigint" ? value.toString() : value;
}
function substring(str, length = 10) {
if (str.length < length * 2) {
return str;
}
return `${str.substring(0, length)}...${str.substring(str.length - length)}`;
}
function digest(bytes, algo = "SHA-384") {
return __async$d(this, null, function* () {
return new Uint8Array(yield crypto.subtle.digest(algo, bytes));
});
}
var __defProp$4 = Object.defineProperty;
var __defProps$3 = Object.defineProperties;
var __getOwnPropDescs$3 = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols$4 = Object.getOwnPropertySymbols;
var __getProtoOf$1 = Object.getPrototypeOf;
var __hasOwnProp$4 = Object.prototype.hasOwnProperty;
var __propIsEnum$4 = Object.prototype.propertyIsEnumerable;
var __reflectGet$1 = Reflect.get;
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues$4 = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp$4.call(b, prop))
__defNormalProp$4(a, prop, b[prop]);
if (__getOwnPropSymbols$4)
for (var prop of __getOwnPropSymbols$4(b)) {
if (__propIsEnum$4.call(b, prop))
__defNormalProp$4(a, prop, b[prop]);
}
return a;
};
var __spreadProps$3 = (a, b) => __defProps$3(a, __getOwnPropDescs$3(b));
var __superGet$1 = (cls, obj, key) => __reflectGet$1(__getProtoOf$1(cls), key, obj);
var __async$c = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
const defaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0";
const fetch = crossFetch;
function getHttpAgent({
fetchUrl,
proxyUrl,
torPort,
retry
}) {
const { HttpProxyAgent } = require("http-proxy-agent");
const { HttpsProxyAgent } = require("https-proxy-agent");
const { SocksProxyAgent } = require("socks-proxy-agent");
if (torPort) {
return new SocksProxyAgent(`socks5h://tor${retry}@127.0.0.1:${torPort}`);
}
if (!proxyUrl) {
return;
}
const isHttps = fetchUrl.includes("https://");
if (proxyUrl.includes("socks://") || proxyUrl.includes("socks4://") || proxyUrl.includes("socks5://")) {
return new SocksProxyAgent(proxyUrl);
}
if (proxyUrl.includes("http://") || proxyUrl.includes("https://")) {
if (isHttps) {
return new HttpsProxyAgent(proxyUrl);
}
return new HttpProxyAgent(proxyUrl);
}
}
function fetchData(_0) {
return __async$c(this, arguments, function* (url, options = {}) {
var _a, _b, _c;
const MAX_RETRY = (_a = options.maxRetry) != null ? _a : 3;
const RETRY_ON = (_b = options.retryOn) != null ? _b : 500;
const userAgent = (_c = options.userAgent) != null ? _c : defaultUserAgent;
let retry = 0;
let errorObject;
if (!options.method) {
if (!options.body) {
options.method = "GET";
} else {
options.method = "POST";
}
}
if (!options.headers) {
options.headers = {};
}
if (isNode && !options.headers["User-Agent"]) {
options.headers["User-Agent"] = userAgent;
}
while (retry < MAX_RETRY + 1) {
let timeout;
if (!options.signal && options.timeout) {
const controller = new AbortController();
options.signal = controller.signal;
timeout = setTimeout(() => {
controller.abort();
}, options.timeout);
}
if (!options.agent && isNode && (options.proxy || options.torPort)) {
options.agent = getHttpAgent({
fetchUrl: url,
proxyUrl: options.proxy,
torPort: options.torPort,
retry
});
}
if (options.debug && typeof options.debug === "function") {
options.debug("request", {
url,
retry,
errorObject,
options
});
}
try {
const resp = yield fetch(url, {
method: options.method,
headers: options.headers,
body: options.body,
redirect: options.redirect,
signal: options.signal,
agent: options.agent
});
if (options.debug && typeof options.debug === "function") {
options.debug("response", resp);
}
if (!resp.ok) {
const errMsg = `Request to ${url} failed with error code ${resp.status}:
` + (yield resp.text());
throw new Error(errMsg);
}
if (options.returnResponse) {
return resp;
}
const contentType = resp.headers.get("content-type");
if (contentType == null ? void 0 : contentType.includes("application/json")) {
return yield resp.json();
}
if (contentType == null ? void 0 : contentType.includes("text")) {
return yield resp.text();
}
return resp;
} catch (error) {
if (timeout) {
clearTimeout(timeout);
}
errorObject = error;
retry++;
yield sleep(RETRY_ON);
} finally {
if (timeout) {
clearTimeout(timeout);
}
}
}
if (options.debug && typeof options.debug === "function") {
options.debug("error", errorObject);
}
throw errorObject;
});
}
const fetchGetUrlFunc = (options = {}) => (req, _signal) => __async$c(void 0, null, function* () {
let signal;
if (_signal) {
const controller = new AbortController();
signal = controller.signal;
_signal.addListener(() => {
controller.abort();
});
}
const init = __spreadProps$3(__spreadValues$4({}, options), {
method: req.method || "POST",
headers: req.headers,
body: req.body || void 0,
signal,
returnResponse: true
});
const resp = yield fetchData(req.url, init);
const headers = {};
resp.headers.forEach((value, key) => {
headers[key.toLowerCase()] = value;
});
const respBody = yield resp.arrayBuffer();
const body = respBody == null ? null : new Uint8Array(respBody);
return {
statusCode: resp.status,
statusMessage: resp.statusText,
headers,
body
};
});
function getProvider(rpcUrl, fetchOptions) {
return __async$c(this, null, function* () {
const fetchReq = new ethers.FetchRequest(rpcUrl);
fetchReq.getUrlFunc = fetchGetUrlFunc(fetchOptions);
const staticNetwork = yield new ethers.JsonRpcProvider(fetchReq).getNetwork();
const chainId = Number(staticNetwork.chainId);
if ((fetchOptions == null ? void 0 : fetchOptions.netId) && fetchOptions.netId !== chainId) {
const errMsg = `Wrong network for ${rpcUrl}, wants ${fetchOptions.netId} got ${chainId}`;
throw new Error(errMsg);
}
return new ethers.JsonRpcProvider(fetchReq, staticNetwork, {
staticNetwork,
pollingInterval: (fetchOptions == null ? void 0 : fetchOptions.pollingInterval) || 1e3
});
});
}
function getProviderWithNetId(netId, rpcUrl, config, fetchOptions) {
const { networkName, reverseRecordsContract, pollInterval } = config;
const hasEns = Boolean(reverseRecordsContract);
const fetchReq = new ethers.FetchRequest(rpcUrl);
fetchReq.getUrlFunc = fetchGetUrlFunc(fetchOptions);
const staticNetwork = new ethers.Network(networkName, netId);
if (hasEns) {
staticNetwork.attachPlugin(new ethers.EnsPlugin(null, Number(netId)));
}
staticNetwork.attachPlugin(new ethers.GasCostPlugin());
const provider = new ethers.JsonRpcProvider(fetchReq, staticNetwork, {
staticNetwork,
pollingInterval: (fetchOptions == null ? void 0 : fetchOptions.pollingInterval) || pollInterval * 1e3
});
return provider;
}
const populateTransaction = (signer, tx) => __async$c(void 0, null, function* () {
const provider = signer.provider;
if (!tx.from) {
tx.from = signer.address;
} else if (tx.from !== signer.address) {
const errMsg = `populateTransaction: signer mismatch for tx, wants ${tx.from} have ${signer.address}`;
throw new Error(errMsg);
}
const [feeData, nonce] = yield Promise.all([
(() => __async$c(void 0, null, function* () {
if (tx.maxFeePerGas && tx.maxPriorityFeePerGas) {
return new ethers.FeeData(null, BigInt(tx.maxFeePerGas), BigInt(tx.maxPriorityFeePerGas));
}
if (tx.gasPrice) {
return new ethers.FeeData(BigInt(tx.gasPrice), null, null);
}
const fetchedFeeData = yield provider.getFeeData();
if (fetchedFeeData.maxFeePerGas && fetchedFeeData.maxPriorityFeePerGas) {
return new ethers.FeeData(
null,
fetchedFeeData.maxFeePerGas * (BigInt(1e4) + BigInt(signer.gasPriceBump)) / BigInt(1e4),
fetchedFeeData.maxPriorityFeePerGas
);
} else {
return new ethers.FeeData(
fetchedFeeData.gasPrice * (BigInt(1e4) + BigInt(signer.gasPriceBump)) / BigInt(1e4),
null,
null
);
}
}))(),
(() => __async$c(void 0, null, function* () {
if (tx.nonce) {
return tx.nonce;
}
let fetchedNonce = yield provider.getTransactionCount(signer.address, "pending");
if (signer.bumpNonce && signer.nonce && signer.nonce >= fetchedNonce) {
console.log(
`populateTransaction: bumping nonce from ${fetchedNonce} to ${fetchedNonce + 1} for ${signer.address}`
);
fetchedNonce++;
}
return fetchedNonce;
}))()
]);
tx.nonce = nonce;
if (feeData.maxFeePerGas && feeData.maxPriorityFeePerGas) {
tx.maxFeePerGas = feeData.maxFeePerGas;
tx.maxPriorityFeePerGas = feeData.maxPriorityFeePerGas;
if (!tx.type) {
tx.type = 2;
}
delete tx.gasPrice;
} else if (feeData.gasPrice) {
tx.gasPrice = feeData.gasPrice;
if (!tx.type) {
tx.type = 0;
}
delete tx.maxFeePerGas;
delete tx.maxPriorityFeePerGas;
}
tx.gasLimit = tx.gasLimit || (yield (() => __async$c(void 0, null, function* () {
try {
const gasLimit = yield provider.estimateGas(tx);
return gasLimit === BigInt(21e3) ? gasLimit : gasLimit * (BigInt(1e4) + BigInt(signer.gasLimitBump)) / BigInt(1e4);
} catch (err) {
if (signer.gasFailover) {
console.log("populateTransaction: warning gas estimation failed falling back to 3M gas");
return BigInt("3000000");
}
throw err;
}
}))());
return tx;
});
class TornadoWallet extends ethers.Wallet {
constructor(key, provider, { gasPriceBump, gasLimitBump, gasFailover, bumpNonce } = {}) {
super(key, provider);
this.gasPriceBump = gasPriceBump != null ? gasPriceBump : 0;
this.gasLimitBump = gasLimitBump != null ? gasLimitBump : 3e3;
this.gasFailover = gasFailover != null ? gasFailover : false;
this.bumpNonce = bumpNonce != null ? bumpNonce : false;
}
static fromMnemonic(mneomnic, provider, index = 0, options) {
const defaultPath = `m/44'/60'/0'/0/${index}`;
const { privateKey } = ethers.HDNodeWallet.fromPhrase(mneomnic, void 0, defaultPath);
return new TornadoWallet(privateKey, provider, options);
}
populateTransaction(tx) {
return __async$c(this, null, function* () {
const txObject = yield populateTransaction(this, tx);
this.nonce = txObject.nonce;
return __superGet$1(TornadoWallet.prototype, this, "populateTransaction").call(this, txObject);
});
}
}
class TornadoVoidSigner extends ethers.VoidSigner {
constructor(address, provider, { gasPriceBump, gasLimitBump, gasFailover, bumpNonce } = {}) {
super(address, provider);
this.gasPriceBump = gasPriceBump != null ? gasPriceBump : 0;
this.gasLimitBump = gasLimitBump != null ? gasLimitBump : 3e3;
this.gasFailover = gasFailover != null ? gasFailover : false;
this.bumpNonce = bumpNonce != null ? bumpNonce : false;
}
populateTransaction(tx) {
return __async$c(this, null, function* () {
const txObject = yield populateTransaction(this, tx);
this.nonce = txObject.nonce;
return __superGet$1(TornadoVoidSigner.prototype, this, "populateTransaction").call(this, txObject);
});
}
}
class TornadoRpcSigner extends ethers.JsonRpcSigner {
constructor(provider, address, { gasPriceBump, gasLimitBump, gasFailover, bumpNonce } = {}) {
super(provider, address);
this.gasPriceBump = gasPriceBump != null ? gasPriceBump : 0;
this.gasLimitBump = gasLimitBump != null ? gasLimitBump : 3e3;
this.gasFailover = gasFailover != null ? gasFailover : false;
this.bumpNonce = bumpNonce != null ? bumpNonce : false;
}
sendUncheckedTransaction(tx) {
return __async$c(this, null, function* () {
return __superGet$1(TornadoRpcSigner.prototype, this, "sendUncheckedTransaction").call(this, yield populateTransaction(this, tx));
});
}
}
class TornadoBrowserProvider extends ethers.BrowserProvider {
constructor(ethereum, network, options) {
super(ethereum, network);
this.options = options;
}
getSigner(address) {
return __async$c(this, null, function* () {
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
const signerAddress = (yield __superGet$1(TornadoBrowserProvider.prototype, this, "getSigner").call(this, address)).address;
if (((_a = this.options) == null ? void 0 : _a.webChainId) && ((_b = this.options) == null ? void 0 : _b.connectWallet) && Number(yield __superGet$1(TornadoBrowserProvider.prototype, this, "send").call(this, "eth_chainId", [])) !== Number((_c = this.options) == null ? void 0 : _c.webChainId)) {
yield this.options.connectWallet();
}
if ((_d = this.options) == null ? void 0 : _d.handleNetworkChanges) {
(_e = window == null ? void 0 : window.ethereum) == null ? void 0 : _e.on("chainChanged", this.options.handleNetworkChanges);
}
if ((_f = this.options) == null ? void 0 : _f.handleAccountChanges) {
(_g = window == null ? void 0 : window.ethereum) == null ? void 0 : _g.on("accountsChanged", this.options.handleAccountChanges);
}
if ((_h = this.options) == null ? void 0 : _h.handleAccountDisconnect) {
(_i = window == null ? void 0 : window.ethereum) == null ? void 0 : _i.on("disconnect", this.options.handleAccountDisconnect);
}
return new TornadoRpcSigner(this, signerAddress, this.options);
});
}
}
const GET_STATISTIC = `
query getStatistic($currency: String!, $amount: String!, $first: Int, $orderBy: BigInt, $orderDirection: String) {
deposits(first: $first, orderBy: $orderBy, orderDirection: $orderDirection, where: { currency: $currency, amount: $amount }) {
index
timestamp
blockNumber
}
_meta {
block {
number
}
hasIndexingErrors
}
}
`;
const _META = `
query getMeta {
_meta {
block {
number
}
hasIndexingErrors
}
}
`;
const GET_REGISTERED = `
query getRegistered($first: Int, $fromBlock: Int) {
relayers(first: $first, orderBy: blockRegistration, orderDirection: asc, where: {
blockRegistration_gte: $fromBlock
}) {
id
address
ensName
blockRegistration
}
_meta {
block {
number
}
hasIndexingErrors
}
}
`;
const GET_DEPOSITS = `
query getDeposits($currency: String!, $amount: String!, $first: Int, $fromBlock: Int) {
deposits(first: $first, orderBy: index, orderDirection: asc, where: {
amount: $amount,
currency: $currency,
blockNumber_gte: $fromBlock
}) {
id
blockNumber
commitment
index
timestamp
from
}
_meta {
block {
number
}
hasIndexingErrors
}
}
`;
const GET_WITHDRAWALS = `
query getWithdrawals($currency: String!, $amount: String!, $first: Int, $fromBlock: Int!) {
withdrawals(first: $first, orderBy: blockNumber, orderDirection: asc, where: {
currency: $currency,
amount: $amount,
blockNumber_gte: $fromBlock
}) {
id
blockNumber
nullifier
to
fee
timestamp
}
_meta {
block {
number
}
hasIndexingErrors
}
}
`;
const GET_NOTE_ACCOUNTS = `
query getNoteAccount($address: String!) {
noteAccounts(where: { address: $address }) {
id
index
address
encryptedAccount
}
_meta {
block {
number
}
hasIndexingErrors
}
}
`;
const GET_ECHO_EVENTS = `
query getNoteAccounts($first: Int, $fromBlock: Int) {
noteAccounts(first: $first, orderBy: blockNumber, orderDirection: asc, where: { blockNumber_gte: $fromBlock }) {
id
blockNumber
address
encryptedAccount
}
_meta {
block {
number
}
hasIndexingErrors
}
}
`;
const GET_ENCRYPTED_NOTES = `
query getEncryptedNotes($first: Int, $fromBlock: Int) {
encryptedNotes(first: $first, orderBy: blockNumber, orderDirection: asc, where: { blockNumber_gte: $fromBlock }) {
blockNumber
index
transactionHash
encryptedNote
}
_meta {
block {
number
}
hasIndexingErrors
}
}
`;
const GET_GOVERNANCE_EVENTS = `
query getGovernanceEvents($first: Int, $fromBlock: Int) {
proposals(first: $first, orderBy: blockNumber, orderDirection: asc, where: { blockNumber_gte: $fromBlock }) {
blockNumber
logIndex
transactionHash
proposalId
proposer
target
startTime
endTime
description
}
votes(first: $first, orderBy: blockNumber, orderDirection: asc, where: { blockNumber_gte: $fromBlock }) {
blockNumber
logIndex
transactionHash
proposalId
voter
support
votes
from
input
}
delegates(first: $first, orderBy: blockNumber, orderDirection: asc, where: { blockNumber_gte: $fromBlock }) {
blockNumber
logIndex
transactionHash
account
delegateTo
}
undelegates(first: $first, orderBy: blockNumber, orderDirection: asc, where: { blockNumber_gte: $fromBlock }) {
blockNumber
logIndex
transactionHash
account
delegateFrom
}
_meta {
block {
number
}
hasIndexingErrors
}
}
`;
const GET_GOVERNANCE_APY = `
stakeDailyBurns(first: 30, orderBy: date, orderDirection: desc) {
id
date
dailyAmountBurned
}
`;
var __defProp$3 = Object.defineProperty;
var __defProps$2 = Object.defineProperties;
var __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols$3 = Object.getOwnPropertySymbols;
var __hasOwnProp$3 = Object.prototype.hasOwnProperty;
var __propIsEnum$3 = Object.prototype.propertyIsEnumerable;
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues$3 = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp$3.call(b, prop))
__defNormalProp$3(a, prop, b[prop]);
if (__getOwnPropSymbols$3)
for (var prop of __getOwnPropSymbols$3(b)) {
if (__propIsEnum$3.call(b, prop))
__defNormalProp$3(a, prop, b[prop]);
}
return a;
};
var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
var __async$b = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
const isEmptyArray = (arr) => !Array.isArray(arr) || !arr.length;
const GRAPHQL_LIMIT = 1e3;
function queryGraph(_0) {
return __async$b(this, arguments, function* ({
graphApi,
subgraphName,
query,
variables,
fetchDataOptions: fetchDataOptions2
}) {
var _a;
const graphUrl = `${graphApi}/subgraphs/name/${subgraphName}`;
const { data, errors } = yield fetchData(graphUrl, __spreadProps$2(__spreadValues$3({}, fetchDataOptions2), {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
query,
variables
})
}));
if (errors) {
throw new Error(JSON.stringify(errors));
}
if ((_a = data == null ? void 0 : data._meta) == null ? void 0 : _a.hasIndexingErrors) {
throw new Error("Subgraph has indexing errors");
}
return data;
});
}
function getStatistic(_0) {
return __async$b(this, arguments, function* ({
graphApi,
subgraphName,
currency,
amount,
fetchDataOptions: fetchDataOptions2
}) {
try {
const {
deposits,
_meta: {
block: { number: lastSyncBlock }
}
} = yield queryGraph({
graphApi,
subgraphName,
query: GET_STATISTIC,
variables: {
currency,
first: 10,
orderBy: "index",
orderDirection: "desc",
amount
},
fetchDataOptions: fetchDataOptions2
});
const events = deposits.map((e) => ({
timestamp: Number(e.timestamp),
leafIndex: Number(e.index),
blockNumber: Number(e.blockNumber)
})).reverse();
const [lastEvent] = events.slice(-1);
return {
events,
lastSyncBlock: lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock
};
} catch (err) {
console.log("Error from getStatistic query");
console.log(err);
return {
events: [],
lastSyncBlock: null
};
}
});
}
function getMeta(_0) {
return __async$b(this, arguments, function* ({ graphApi, subgraphName, fetchDataOptions: fetchDataOptions2 }) {
try {
const {
_meta: {
block: { number: lastSyncBlock },
hasIndexingErrors
}
} = yield queryGraph({
graphApi,
subgraphName,
query: _META,
fetchDataOptions: fetchDataOptions2
});
return {
lastSyncBlock,
hasIndexingErrors
};
} catch (err) {
console.log("Error from getMeta query");
console.log(err);
return {
lastSyncBlock: null,
hasIndexingErrors: null
};
}
});
}
function getRegisters({
graphApi,
subgraphName,
fromBlock,
fetchDataOptions: fetchDataOptions2
}) {
return queryGraph({
graphApi,
subgraphName,
query: GET_REGISTERED,
variables: {
first: GRAPHQL_LIMIT,
fromBlock
},
fetchDataOptions: fetchDataOptions2
});
}
function getAllRegisters(_0) {
return __async$b(this, arguments, function* ({
graphApi,
subgraphName,
fromBlock,
fetchDataOptions: fetchDataOptions2,
onProgress
}) {
try {
const events = [];
let lastSyncBlock = fromBlock;
while (true) {
let {
relayers: result2,
_meta: {
// eslint-disable-next-line prefer-const
block: { number: currentBlock }
}
} = yield getRegisters({ graphApi, subgraphName, fromBlock, fetchDataOptions: fetchDataOptions2 });
lastSyncBlock = currentBlock;
if (isEmptyArray(result2)) {
break;
}
const [firstEvent] = result2;
const [lastEvent] = result2.slice(-1);
if (typeof onProgress === "function") {
onProgress({
type: "Registers",
fromBlock: Number(firstEvent.blockRegistration),
toBlock: Number(lastEvent.blockRegistration),
count: result2.length
});
}
if (result2.length < 900) {
events.push(...result2);
break;
}
result2 = result2.filter(({ blockRegistration }) => blockRegistration !== lastEvent.blockRegistration);
fromBlock = Number(lastEvent.blockRegistration);
events.push(...result2);
}
if (!events.length) {
return {
events: [],
lastSyncBlock
};
}
const result = events.map(({ id, address, ensName, blockRegistration }) => {
const [transactionHash, logIndex] = id.split("-");
return {
blockNumber: Number(blockRegistration),
logIndex: Number(logIndex),
transactionHash,
ensName,
relayerAddress: ethers.getAddress(address)
};
});
return {
events: result,
lastSyncBlock
};
} catch (err) {
console.log("Error from getAllRegisters query");
console.log(err);
return { events: [], lastSyncBlock: fromBlock };
}
});
}
function getDeposits({
graphApi,
subgraphName,
currency,
amount,
fromBlock,
fetchDataOptions: fetchDataOptions2
}) {
return queryGraph({
graphApi,
subgraphName,
query: GET_DEPOSITS,
variables: {
currency,
amount,
first: GRAPHQL_LIMIT,
fromBlock
},
fetchDataOptions: fetchDataOptions2
});
}
function getAllDeposits(_0) {
return __async$b(this, arguments, function* ({
graphApi,
subgraphName,
currency,
amount,
fromBlock,
fetchDataOptions: fetchDataOptions2,
onProgress
}) {
try {
const events = [];
let lastSyncBlock = fromBlock;
while (true) {
let {
deposits: result2,
_meta: {
// eslint-disable-next-line prefer-const
block: { number: currentBlock }
}
} = yield getDeposits({ graphApi, subgraphName, currency, amount, fromBlock, fetchDataOptions: fetchDataOptions2 });
lastSyncBlock = currentBlock;
if (isEmptyArray(result2)) {
break;
}
const [firstEvent] = result2;
const [lastEvent2] = result2.slice(-1);
if (typeof onProgress === "function") {
onProgress({
type: "Deposits",
fromBlock: Number(firstEvent.blockNumber),
toBlock: Number(lastEvent2.blockNumber),
count: result2.length
});
}
if (result2.length < 900) {
events.push(...result2);
break;
}
result2 = result2.filter(({ blockNumber }) => blockNumber !== lastEvent2.blockNumber);
fromBlock = Number(lastEvent2.blockNumber);
events.push(...result2);
}
if (!events.length) {
return {
events: [],
lastSyncBlock
};
}
const result = events.map(({ id, blockNumber, commitment, index, timestamp, from }) => {
const [transactionHash, logIndex] = id.split("-");
return {
blockNumber: Number(blockNumber),
logIndex: Number(logIndex),
transactionHash,
commitment,
leafIndex: Number(index),
timestamp: Number(timestamp),
from: ethers.getAddress(from)
};
});
const [lastEvent] = result.slice(-1);
return {
events: result,
lastSyncBlock: lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock
};
} catch (err) {
console.log("Error from getAllDeposits query");
console.log(err);
return {
events: [],
lastSyncBlock: fromBlock
};
}
});
}
function getWithdrawals({
graphApi,
subgraphName,
currency,
amount,
fromBlock,
fetchDataOptions: fetchDataOptions2
}) {
return queryGraph({
graphApi,
subgraphName,
query: GET_WITHDRAWALS,
variables: {
currency,
amount,
first: GRAPHQL_LIMIT,
fromBlock
},
fetchDataOptions: fetchDataOptions2
});
}
function getAllWithdrawals(_0) {
return __async$b(this, arguments, function* ({
graphApi,
subgraphName,
currency,
amount,
fromBlock,
fetchDataOptions: fetchDataOptions2,
onProgress
}) {
try {
const events = [];
let lastSyncBlock = fromBlock;
while (true) {
let {
withdrawals: result2,
_meta: {
// eslint-disable-next-line prefer-const
block: { number: currentBlock }
}
} = yield getWithdrawals({ graphApi, subgraphName, currency, amount, fromBlock, fetchDataOptions: fetchDataOptions2 });
lastSyncBlock = currentBlock;
if (isEmptyArray(result2)) {
break;
}
const [firstEvent] = result2;
const [lastEvent2] = result2.slice(-1);
if (typeof onProgress === "function") {
onProgress({
type: "Withdrawals",
fromBlock: Number(firstEvent.blockNumber),
toBlock: Number(lastEvent2.blockNumber),
count: result2.length
});
}
if (result2.length < 900) {
events.push(...result2);
break;
}
result2 = result2.filter(({ blockNumber }) => blockNumber !== lastEvent2.blockNumber);
fromBlock = Number(lastEvent2.blockNumber);
events.push(...result2);
}
if (!events.length) {
return {
events: [],
lastSyncBlock
};
}
const result = events.map(({ id, blockNumber, nullifier, to, fee, timestamp }) => {
const [transactionHash, logIndex] = id.split("-");
return {
blockNumber: Number(blockNumber),
logIndex: Number(logIndex),
transactionHash,
nullifierHash: nullifier,
to: ethers.getAddress(to),
fee,
timestamp: Number(timestamp)
};
});
const [lastEvent] = result.slice(-1);
return {
events: result,
lastSyncBlock: lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock
};
} catch (err) {
console.log("Error from getAllWithdrawals query");
console.log(err);
return {
events: [],
lastSyncBlock: fromBlock
};
}
});
}
function getNoteAccounts(_0) {
return __async$b(this, arguments, function* ({
graphApi,
subgraphName,
address,
fetchDataOptions: fetchDataOptions2
}) {
try {
const {
noteAccounts: events,
_meta: {
block: { number: lastSyncBlock }
}
} = yield queryGraph({
graphApi,
subgraphName,
query: GET_NOTE_ACCOUNTS,
variables: {
address: address.toLowerCase()
},
fetchDataOptions: fetchDataOptions2
});
return {
events,
lastSyncBlock
};
} catch (err) {
console.log("Error from getNoteAccounts query");
console.log(err);
return {
events: [],
lastSyncBlock: null
};
}
});
}
function getGraphEchoEvents({
graphApi,
subgraphName,
fromBlock,
fetchDataOptions: fetchDataOptions2
}) {
return queryGraph({
graphApi,
subgraphName,
query: GET_ECHO_EVENTS,
variables: {
first: GRAPHQL_LIMIT,
fromBlock
},
fetchDataOptions: fetchDataOptions2
});
}
function getAllGraphEchoEvents(_0) {
return __async$b(this, arguments, function* ({
graphApi,
subgraphName,
fromBlock,
fetchDataOptions: fetchDataOptions2,
onProgress
}) {
try {
const events = [];
let lastSyncBlock = fromBlock;
while (true) {
let {
noteAccounts: result2,
_meta: {
// eslint-disable-next-line prefer-const
block: { number: currentBlock }
}
} = yield getGraphEchoEvents({ graphApi, subgraphName, fromBlock, fetchDataOptions: fetchDataOptions2 });
lastSyncBlock = currentBlock;
if (isEmptyArray(result2)) {
break;
}
const [firstEvent] = result2;
const [lastEvent2] = result2.slice(-1);
if (typeof onProgress === "function") {
onProgress({
type: "EchoEvents",
fromBlock: Number(firstEvent.blockNumber),
toBlock: Number(lastEvent2.blockNumber),
count: result2.length
});
}
if (result2.length < 900) {
events.push(...result2);
break;
}
result2 = result2.filter(({ blockNumber }) => blockNumber !== lastEvent2.blockNumber);
fromBlock = Number(lastEvent2.blockNumber);
events.push(...result2);
}
if (!events.length) {
return {
events: [],
lastSyncBlock
};
}
const result = events.map((e) => {
const [transactionHash, logIndex] = e.id.split("-");
return {
blockNumber: Number(e.blockNumber),
logIndex: Number(logIndex),
transactionHash,
address: ethers.getAddress(e.address),
encryptedAccount: e.encryptedAccount
};
});
const [lastEvent] = result.slice(-1);
return {
events: result,
lastSyncBlock: lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock
};
} catch (err) {
console.log("Error from getAllGraphEchoEvents query");
console.log(err);
return {
events: [],
lastSyncBlock: fromBlock
};
}
});
}
function getEncryptedNotes({
graphApi,
subgraphName,
fromBlock,
fetchDataOptions: fetchDataOptions2
}) {
return queryGraph({
graphApi,
subgraphName,
query: GET_ENCRYPTED_NOTES,
variables: {
first: GRAPHQL_LIMIT,
fromBlock
},
fetchDataOptions: fetchDataOptions2
});
}
function getAllEncryptedNotes(_0) {
return __async$b(this, arguments, function* ({
graphApi,
subgraphName,
fromBlock,
fetchDataOptions: fetchDataOptions2,
onProgress
}) {
try {
const events = [];
let lastSyncBlock = fromBlock;
while (true) {
let {
encryptedNotes: result2,
_meta: {
// eslint-disable-next-line prefer-const
block: { number: currentBlock }
}
} = yield getEncryptedNotes({ graphApi, subgraphName, fromBlock, fetchDataOptions: fetchDataOptions2 });
lastSyncBlock = currentBlock;
if (isEmptyArray(result2)) {
break;
}
const [firstEvent] = result2;
const [lastEvent2] = result2.slice(-1);
if (typeof onProgress === "function") {
onProgress({
type: "EncryptedNotes",
fromBlock: Number(firstEvent.blockNumber),
toBlock: Number(lastEvent2.blockNumber),
count: result2.length
});
}
if (result2.length < 900) {
events.push(...result2);
break;
}
result2 = result2.filter(({ blockNumber }) => blockNumber !== lastEvent2.blockNumber);
fromBlock = Number(lastEvent2.blockNumber);
events.push(...result2);
}
if (!events.length) {
return {
events: [],
lastSyncBlock
};
}
const result = events.map((e) => ({
blockNumber: Number(e.blockNumber),
logIndex: Number(e.index),
transactionHash: e.transactionHash,
encryptedNote: e.encryptedNote
}));
const [lastEvent] = result.slice(-1);
return {
events: result,
lastSyncBlock: lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock
};
} catch (err) {
console.log("Error from getAllEncryptedNotes query");
console.log(err);
return {
events: [],
lastSyncBlock: fromBlock
};
}
});
}
function getGovernanceEvents({
graphApi,
subgraphName,
fromBlock,
fetchDataOptions: fetchDataOptions2
}) {
return queryGraph({
graphApi,
subgraphName,
query: GET_GOVERNANCE_EVENTS,
variables: {
first: GRAPHQL_LIMIT,
fromBlock
},
fetchDataOptions: fetchDataOptions2
});
}
function getAllGovernanceEvents(_0) {
return __async$b(this, arguments, function* ({
graphApi,
subgraphName,
fromBlock,
fetchDataOptions: fetchDataOptions2,
onProgress
}) {
try {
const result = [];
let lastSyncBlock = fromBlock;
while (true) {
const {
proposals,
votes,
delegates,
undelegates,
_meta: {
block: { number: currentBlock }
}
} = yield getGovernanceEvents({ graphApi, subgraphName, fromBlock, fetchDataOptions: fetchDataOptions2 });
lastSyncBlock = currentBlock;
const eventsLength = proposals.length + votes.length + delegates.length + undelegates.length;
if (eventsLength === 0) {
break;
}
const formattedProposals = proposals.map(
({ blockNumber, logIndex, transactionHash, proposalId, proposer, target, startTime, endTime, description }) => {
return {
blockNumber: Number(blockNumber),
logIndex: Number(logIndex),
transactionHash,
event: "ProposalCreated",
id: Number(proposalId),
proposer: ethers.getAddress(proposer),
target: ethers.getAddress(target),
startTime: Number(startTime),
endTime: Number(endTime),
description
};
}
);
const formattedVotes = votes.map(
({ blockNumber, logIndex, transactionHash, proposalId, voter, support, votes: votes2, from, input }) => {
if (!input || input.length > 2048) {
input = "";
}
return {
blockNumber: Number(blockNumber),
logIndex: Number(logIndex),
transactionHash,
event: "Voted",
proposalId: Number(proposalId),
voter: ethers.getAddress(voter),
support,
votes: votes2,
from: ethers.getAddress(from),
input
};
}
);
const formattedDelegates = delegates.map(
({ blockNumber, logIndex, transactionHash, account, delegateTo }) => {
return {
blockNumber: Number(blockNumber),
logIndex: Number(logIndex),
transactionHash,
event: "Delegated",
account: ethers.getAddress(account),
delegateTo: ethers.getAddress(delegateTo)
};
}
);
const formattedUndelegates = undelegates.map(
({ blockNumber, logIndex, transactionHash, account, delegateFrom }) => {
return {
blockNumber: Number(blockNumber),
logIndex: Number(logIndex),
transactionHash,
event: "Undelegated",
account: ethers.getAddress(account),
delegateFrom: ethers.getAddress(delegateFrom)
};
}
);
let formattedEvents = [
...formattedProposals,
...formattedVotes,
...formattedDelegates,
...formattedUndelegates
].sort((a, b) => {
if (a.blockNumber === b.blockNumber) {
return a.logIndex - b.logIndex;
}
return a.blockNumber - b.blockNumber;
});
if (eventsLength < 900) {
result.push(...formattedEvents);
break;
}
const [firstEvent] = formattedEvents;
const [lastEvent2] = formattedEvents.slice(-1);
if (typeof onProgress === "function") {
onProgress({
type: "Governance Events",
fromBlock: Number(firstEvent.blockNumber),
toBlock: Number(lastEvent2.blockNumber),
count: eventsLength
});
}
formattedEvents = formattedEvents.filter(({ blockNumber }) => blockNumber !== lastEvent2.blockNumber);
fromBlock = Number(lastEvent2.blockNumber);
result.push(...formattedEvents);
}
const [lastEvent] = result.slice(-1);
return {
events: result,
lastSyncBlock: lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock
};
} catch (err) {
console.log("Error from getAllGovernance query");
console.log(err);
return {
events: [],
lastSyncBlock: fromBlock
};
}
});
}
var graph = /*#__PURE__*/Object.freeze({
__proto__: null,
GET_DEPOSITS: GET_DEPOSITS,
GET_ECHO_EVENTS: GET_ECHO_EVENTS,
GET_ENCRYPTED_NOTES: GET_ENCRYPTED_NOTES,
GET_GOVERNANCE_APY: GET_GOVERNANCE_APY,
GET_GOVERNANCE_EVENTS: GET_GOVERNANCE_EVENTS,
GET_NOTE_ACCOUNTS: GET_NOTE_ACCOUNTS,
GET_REGISTERED: GET_REGISTERED,
GET_STATISTIC: GET_STATISTIC,
GET_WITHDRAWALS: GET_WITHDRAWALS,
_META: _META,
getAllDeposits: getAllDeposits,
getAllEncryptedNotes: getAllEncryptedNotes,
getAllGovernanceEvents: getAllGovernanceEvents,
getAllGraphEchoEvents: getAllGraphEchoEvents,
getAllRegisters: getAllRegisters,
getAllWithdrawals: getAllWithdrawals,
getDeposits: getDeposits,
getEncryptedNotes: getEncryptedNotes,
getGovernanceEvents: getGovernanceEvents,
getGraphEchoEvents: getGraphEchoEvents,
getMeta: getMeta,
getNoteAccounts: getNoteAccounts,
getRegisters: getRegisters,
getStatistic: getStatistic,
getWithdrawals: getWithdrawals,
queryGraph: queryGraph
});
var __async$a = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
class BatchBlockService {
constructor({
provider,
onProgress,
concurrencySize = 10,
batchSize = 10,
shouldRetry = true,
retryMax = 5,
retryOn = 500
}) {
this.provider = provider;
this.onProgress = onProgress;
this.concurrencySize = concurrencySize;
this.batchSize = batchSize;
this.shouldRetry = shouldRetry;
this.retryMax = retryMax;
this.retryOn = retryOn;
}
getBlock(blockTag) {
return __async$a(this, null, function* () {
const blockObject = yield this.provider.getBlock(blockTag);
if (!blockObject) {
const errMsg = `No block for ${blockTag}`;
throw new Error(errMsg);
}
return blockObject;
});
}
createBatchRequest(batchArray) {
return batchArray.map((blocks, index) => __async$a(this, null, function* () {
yield sleep(20 * index);
return (() => __async$a(this, null, function* () {
let retries = 0;
let err;
while (!this.shouldRetry && retries === 0 || this.shouldRetry && retries < this.retryMax) {
try {
return yield Promise.all(blocks.map((b) => this.getBlock(b)));
} catch (e) {
retries++;
err = e;
yield sleep(this.retryOn);
}
}
throw err;
}))();
}));
}
getBatchBlocks(blocks) {
return __async$a(this, null, function* () {
let blockCount = 0;
const results = [];
for (const chunks of chunk(blocks, this.concurrencySize * this.batchSize)) {
const chunksResult = (yield Promise.all(this.createBatchRequest(chunk(chunks, this.batchSize)))).flat();
results.push(...chunksResult);
blockCount += chunks.length;
if (typeof this.onProgress === "function") {
this.onProgress({
percentage: blockCount / blocks.length,
currentIndex: blockCount,
totalIndex: blocks.length
});
}
}
return results;
});
}
}
class BatchTransactionService {
constructor({
provider,
onProgress,
concurrencySize = 10,
batchSize = 10,
shouldRetry = true,
retryMax = 5,
retryOn = 500
}) {
this.provider = provider;
this.onProgress = onProgress;
this.concurrencySize = concurrencySize;
this.batchSize = batchSize;
this.shouldRetry = shouldRetry;
this.retryMax = retryMax;
this.retryOn = retryOn;
}
getTransaction(txHash) {
return __async$a(this, null, function* () {
const txObject = yield this.provider.getTransaction(txHash);
if (!txObject) {
const errMsg = `No transaction for ${txHash}`;
throw new Error(errMsg);
}
return txObject;
});
}
createBatchRequest(batchArray) {
return batchArray.map((txs, index) => __async$a(this, null, function* () {
yield sleep(20 * index);
return (() => __async$a(this, null, function* () {
let retries = 0;
let err;
while (!this.shouldRetry && retries === 0 || this.shouldRetry && retries < this.retryMax) {
try {
return yield Promise.all(txs.map((tx) => this.getTransaction(tx)));
} catch (e) {
retries++;
err = e;
yield sleep(this.retryOn);
}
}
throw err;
}))();
}));
}
getBatchTransactions(txs) {
return __async$a(this, null, function* () {
let txCount = 0;
const results = [];
for (const chunks of chunk(txs, this.concurrencySize * this.batchSize)) {
const chunksResult = (yield Promise.all(this.createBatchRequest(chunk(chunks, this.batchSize)))).flat();
results.push(...chunksResult);
txCount += chunks.length;
if (typeof this.onProgress === "function") {
this.onProgress({ percentage: txCount / txs.length, currentIndex: txCount, totalIndex: txs.length });
}
}
return results;
});
}
}
class BatchEventsService {
constructor({
provider,
contract,
onProgress,
concurrencySize = 10,
blocksPerRequest = 2e3,
shouldRetry = true,
retryMax = 5,
retryOn = 500
}) {
this.provider = provider;
this.contract = contract;
this.onProgress = onProgress;
this.concurrencySize = concurrencySize;
this.blocksPerRequest = blocksPerRequest;
this.shouldRetry = shouldRetry;
this.retryMax = retryMax;
this.retryOn = retryOn;
}
getPastEvents(_0) {
return __async$a(this, arguments, function* ({ fromBlock, toBlock, type }) {
let err;
let retries = 0;
while (!this.shouldRetry && retries === 0 || this.shouldRetry && retries < this.retryMax) {
try {
return yield this.contract.queryFilter(type, fromBlock, toBlock);
} catch (e) {
err = e;
retries++;
if (e.message.includes("after last accepted block")) {
const acceptedBlock = parseInt(e.message.split("after last accepted block ")[1]);
toBlock = acceptedBlock;
}
yield sleep(this.retryOn);
}
}
throw err;
});
}
createBatchRequest(batchArray) {
return batchArray.map((event, index) => __async$a(this, null, function* () {
yield sleep(20 * index);
return this.getPastEvents(event);
}));
}
getBatchEvents(_0) {
return __async$a(this, arguments, function* ({ fromBlock, toBlock, type = "*" }) {
if (!toBlock) {
toBlock = yield this.provider.getBlockNumber();
}
const eventsToSync = [];
for (let i = fromBlock; i < toBlock; i += this.blocksPerRequest) {
const j = i + this.blocksPerRequest - 1 > toBlock ? toBlock : i + this.blocksPerRequest - 1;
eventsToSync.push({ fromBlock: i, toBlock: j, type });
}
const events = [];
const eventChunk = chunk(eventsToSync, this.concurrencySize);
let chunkCount = 0;
for (const chunk2 of eventChunk) {
chunkCount++;
const fetchedEvents = (yield Promise.all(this.createBatchRequest(chunk2))).flat();
events.push(...fetchedEvents);
if (typeof this.onProgress === "function") {
this.onProgress({
percentage: chunkCount / eventChunk.length,
type,
fromBlock: chunk2[0].fromBlock,
toBlock: chunk2[chunk2.length - 1].toBlock,
count: fetchedEvents.length
});
}
}
return events;
});
}
}
var __defProp$2 = Object.defineProperty;
var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues$2 = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp$2.call(b, prop))
__defNormalProp$2(a, prop, b[prop]);
if (__getOwnPropSymbols$2)
for (var prop of __getOwnPropSymbols$2(b)) {
if (__propIsEnum$2.call(b, prop))
__defNormalProp$2(a, prop, b[prop]);
}
return a;
};
var NetId = /* @__PURE__ */ ((NetId2) => {
NetId2[NetId2["MAINNET"] = 1] = "MAINNET";
NetId2[NetId2["BSC"] = 56] = "BSC";
NetId2[NetId2["POLYGON"] = 137] = "POLYGON";
NetId2[NetId2["OPTIMISM"] = 10] = "OPTIMISM";
NetId2[NetId2["ARBITRUM"] = 42161] = "ARBITRUM";
NetId2[NetId2["GNOSIS"] = 100] = "GNOSIS";
NetId2[NetId2["AVALANCHE"] = 43114] = "AVALANCHE";
NetId2[NetId2["SEPOLIA"] = 11155111] = "SEPOLIA";
return NetId2;
})(NetId || {});
const defaultConfig = {
[1 /* MAINNET */]: {
rpcCallRetryAttempt: 15,
gasPrices: {
instant: 80,
fast: 50,
standard: 25,
low: 8
},
nativeCurrency: "eth",
currencyName: "ETH",
explorerUrl: "https://etherscan.io",
merkleTreeHeight: 20,
emptyElement: "21663839004416932945382355908790599225266501822907911457504978515578255421292",
networkName: "Ethereum Mainnet",
deployedBlock: 9116966,
rpcUrls: {
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"
}
},
multicallContract: "0xcA11bde05977b3631167028862bE2a173976CA11",
routerContract: "0xd90e2f925DA726b50C4Ed8D0Fb90Ad053324F31b",
echoContract: "0x9B27DD5Bb15d42DC224FCD0B7caEbBe16161Df42",
offchainOracleContract: "0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8",
tornContract: "0x77777FeDdddFfC19Ff86DB637967013e6C6A116C",
governanceContract: "0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce",
stakingRewardsContract: "0x5B3f656C80E8ddb9ec01Dd9018815576E9238c29",
registryContract: "0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2",
aggregatorContract: "0xE8F47A78A6D52D317D0D2FFFac56739fE14D1b49",
reverseRecordsContract: "0x3671aE578E63FdF66ad4F3E12CC0c0d71Ac7510C",
tornadoSubgraph: "tornadocash/mainnet-tornado-subgraph",
registrySubgraph: "tornadocash/tornado-relayer-registry",
governanceSubgraph: "tornadocash/tornado-governance",
subgraphs: {},
tokens: {
eth: {
instanceAddress: {
"0.1": "0x12D66f87A04A9E220743712cE6d9bB1B5616B8Fc",
"1": "0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3c2936",
"10": "0x910Cbd523D972eb0a6f4cAe4618aD62622b39DbF",
"100": "0xA160cdAB225685dA1d56aa342Ad8841c3b53f291"
},
symbol: "ETH",
decimals: 18
},
dai: {
instanceAddress: {
"100": "0xD4B88Df4D29F5CedD6857912842cff3b20C8Cfa3",
"1000": "0xFD8610d20aA15b7B2E3Be39B396a1bC3516c7144",
"10000": "0x07687e702b410Fa43f4cB4Af7FA097918ffD2730",
"100000": "0x23773E65ed146A459791799d01336DB287f25334"
},
tokenAddress: "0x6B175474E89094C44Da98b954EedeAC495271d0F",
tokenGasLimit: 7e4,
symbol: "DAI",
decimals: 18,
gasLimit: 7e5
},
cdai: {
instanceAddress: {
"5000": "0x22aaA7720ddd5388A3c0A3333430953C68f1849b",
"50000": "0x03893a7c7463AE47D46bc7f091665f1893656003",
"500000": "0x2717c5e28cf931547B621a5dddb772Ab6A35B701",
"5000000": "0xD21be7248e0197Ee08E0c20D4a96DEBdaC3D20Af"
},
tokenAddress: "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643",
tokenGasLimit: 2e5,
symbol: "cDAI",
decimals: 8,
gasLimit: 7e5
},
usdc: {
instanceAddress: {
"100": "0xd96f2B1c14Db8458374d9Aca76E26c3D18364307",
"1000": "0x4736dCf1b7A3d580672CcE6E7c65cd5cc9cFBa9D"
},
tokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
tokenGasLimit: 7e4,
symbol: "USDC",
decimals: 6,
gasLimit: 7e5
},
usdt: {
instanceAddress: {
"100": "0x169AD27A470D064DEDE56a2D3ff727986b15D52B",
"1000": "0x0836222F2B2B24A3F36f98668Ed8F0B38D1a872f"
},
tokenAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
tokenGasLimit: 7e4,
symbol: "USDT",
decimals: 6,
gasLimit: 7e5
},
wbtc: {
instanceAddress: {
"0.1": "0x178169B423a011fff22B9e3F3abeA13414dDD0F1",
"1": "0x610B717796ad172B316836AC95a2ffad065CeaB4",
"10": "0xbB93e510BbCD0B7beb5A853875f9eC60275CF498"
},
tokenAddress: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
tokenGasLimit: 7e4,
symbol: "WBTC",
decimals: 8,
gasLimit: 7e5
}
},
// Inactive tokens to filter from schema verification and syncing events
disabledTokens: ["cdai", "usdt", "usdc"],
relayerEnsSubdomain: "mainnet-tornado",
pollInterval: 15,
constants: {
GOVERNANCE_BLOCK: 11474695,
NOTE_ACCOUNT_BLOCK: 11842486,
ENCRYPTED_NOTES_BLOCK: 12143762,
REGISTRY_BLOCK: 14173129,
MINING_BLOCK_TIME: 15
}
},
[56 /* BSC */]: {
rpcCallRetryAttempt: 15,
gasPrices: {
instant: 5,
fast: 5,
standard: 5,
low: 5
},
nativeCurrency: "bnb",
currencyName: "BNB",
explorerUrl: "https://bscscan.com",
merkleTreeHeight: 20,
emptyElement: "21663839004416932945382355908790599225266501822907911457504978515578255421292",
networkName: "Binance Smart Chain",
deployedBlock: 8158799,
multicallContract: "0xcA11bde05977b3631167028862bE2a173976CA11",
routerContract: "0x0D5550d52428E7e3175bfc9550207e4ad3859b17",
echoContract: "0xa75BF2815618872f155b7C4B0C81bF990f5245E4",
offchainOracleContract: "0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8",
tornadoSubgraph: "tornadocash/bsc-tornado-subgraph",
subgraphs: {},
rpcUrls: {
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",
url: "https://1rpc.io/bnb"
}
},
tokens: {
bnb: {
instanceAddress: {
"0.1": "0x84443CFd09A48AF6eF360C6976C5392aC5023a1F",
"1": "0xd47438C816c9E7f2E2888E060936a499Af9582b3",
"10": "0x330bdFADE01eE9bF63C209Ee33102DD334618e0a",
"100": "0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD"
},
symbol: "BNB",
decimals: 18
}
},
relayerEnsSubdomain: "bsc-tornado",
pollInterval: 10,
constants: {
NOTE_ACCOUNT_BLOCK: 8159269,
ENCRYPTED_NOTES_BLOCK: 8159269
}
},
[137 /* POLYGON */]: {
rpcCallRetryAttempt: 15,
gasPrices: {
instant: 100,
fast: 75,
standard: 50,
low: 30
},
nativeCurrency: "matic",
currencyName: "MATIC",
explorerUrl: "https://polygonscan.com",
merkleTreeHeight: 20,
emptyElement: "21663839004416932945382355908790599225266501822907911457504978515578255421292",
networkName: "Polygon (Matic) Network",
deployedBlock: 16257962,
multicallContract: "0xcA11bde05977b3631167028862bE2a173976CA11",
routerContract: "0x0D5550d52428E7e3175bfc9550207e4ad3859b17",
echoContract: "0xa75BF2815618872f155b7C4B0C81bF990f5245E4",
offchainOracleContract: "0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8",
tornadoSubgraph: "tornadocash/matic-tornado-subgraph",
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: {
instanceAddress: {
"100": "0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD",
"1000": "0xdf231d99Ff8b6c6CBF4E9B9a945CBAcEF9339178",
"10000": "0xaf4c0B70B2Ea9FB7487C7CbB37aDa259579fe040",
"100000": "0xa5C2254e4253490C54cef0a4347fddb8f75A4998"
},
symbol: "MATIC",
decimals: 18
}
},
relayerEnsSubdomain: "polygon-tornado",
pollInterval: 10,
constants: {
NOTE_ACCOUNT_BLOCK: 16257996,
ENCRYPTED_NOTES_BLOCK: 16257996
}
},
[10 /* OPTIMISM */]: {
rpcCallRetryAttempt: 15,
gasPrices: {
instant: 1e-3,
fast: 1e-3,
standard: 1e-3,
low: 1e-3
},
nativeCurrency: "eth",
currencyName: "ETH",
explorerUrl: "https://optimistic.etherscan.io",
merkleTreeHeight: 20,
emptyElement: "21663839004416932945382355908790599225266501822907911457504978515578255421292",
networkName: "Optimism",
deployedBlock: 2243689,
multicallContract: "0xcA11bde05977b3631167028862bE2a173976CA11",
routerContract: "0x0D5550d52428E7e3175bfc9550207e4ad3859b17",
echoContract: "0xa75BF2815618872f155b7C4B0C81bF990f5245E4",
offchainOracleContract: "0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8",
ovmGasPriceOracleContract: "0x420000000000000000000000000000000000000F",
tornadoSubgraph: "tornadocash/optimism-tornado-subgraph",
subgraphs: {},
rpcUrls: {
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",
url: "https://1rpc.io/op"
}
},
tokens: {
eth: {
instanceAddress: {
"0.1": "0x84443CFd09A48AF6eF360C6976C5392aC5023a1F",
"1": "0xd47438C816c9E7f2E2888E060936a499Af9582b3",
"10": "0x330bdFADE01eE9bF63C209Ee33102DD334618e0a",
"100": "0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD"
},
symbol: "ETH",
decimals: 18
}
},
relayerEnsSubdomain: "optimism-tornado",
pollInterval: 15,
constants: {
NOTE_ACCOUNT_BLOCK: 2243694,
ENCRYPTED_NOTES_BLOCK: 2243694
}
},
[42161 /* ARBITRUM */]: {
rpcCallRetryAttempt: 15,
gasPrices: {
instant: 4,
fast: 3,
standard: 2.52,
low: 2.29
},
nativeCurrency: "eth",
currencyName: "ETH",
explorerUrl: "https://arbiscan.io",
merkleTreeHeight: 20,
emptyElement: "21663839004416932945382355908790599225266501822907911457504978515578255421292",
networkName: "Arbitrum One",
deployedBlock: 3430648,
multicallContract: "0xcA11bde05977b3631167028862bE2a173976CA11",
routerContract: "0x0D5550d52428E7e3175bfc9550207e4ad3859b17",
echoContract: "0xa75BF2815618872f155b7C4B0C81bF990f5245E4",
offchainOracleContract: "0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8",
tornadoSubgraph: "tornadocash/arbitrum-tornado-subgraph",
subgraphs: {},
rpcUrls: {
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: {
instanceAddress: {
"0.1": "0x84443CFd09A48AF6eF360C6976C5392aC5023a1F",
"1": "0xd47438C816c9E7f2E2888E060936a499Af9582b3",
"10": "0x330bdFADE01eE9bF63C209Ee33102DD334618e0a",
"100": "0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD"
},
symbol: "ETH",
decimals: 18
}
},
relayerEnsSubdomain: "arbitrum-tornado",
pollInterval: 15,
constants: {
NOTE_ACCOUNT_BLOCK: 3430605,
ENCRYPTED_NOTES_BLOCK: 3430605
}
},
[100 /* GNOSIS */]: {
rpcCallRetryAttempt: 15,
gasPrices: {
instant: 6,
fast: 5,
standard: 4,
low: 1
},
nativeCurrency: "xdai",
currencyName: "xDAI",
explorerUrl: "https://gnosisscan.io",
merkleTreeHeight: 20,
emptyElement: "21663839004416932945382355908790599225266501822907911457504978515578255421292",
networkName: "Gnosis Chain",
deployedBlock: 17754561,
multicallContract: "0xcA11bde05977b3631167028862bE2a173976CA11",
routerContract: "0x0D5550d52428E7e3175bfc9550207e4ad3859b17",
echoContract: "0xa75BF2815618872f155b7C4B0C81bF990f5245E4",
offchainOracleContract: "0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8",
tornadoSubgraph: "tornadocash/xdai-tornado-subgraph",
subgraphs: {},
rpcUrls: {
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: {
instanceAddress: {
"100": "0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD",
"1000": "0xdf231d99Ff8b6c6CBF4E9B9a945CBAcEF9339178",
"10000": "0xaf4c0B70B2Ea9FB7487C7CbB37aDa259579fe040",
"100000": "0xa5C2254e4253490C54cef0a4347fddb8f75A4998"
},
symbol: "xDAI",
decimals: 18
}
},
relayerEnsSubdomain: "gnosis-tornado",
pollInterval: 15,
constants: {
NOTE_ACCOUNT_BLOCK: 17754564,
ENCRYPTED_NOTES_BLOCK: 17754564
}
},
[43114 /* AVALANCHE */]: {
rpcCallRetryAttempt: 15,
gasPrices: {
instant: 225,
fast: 35,
standard: 25,
low: 25
},
nativeCurrency: "avax",
currencyName: "AVAX",
explorerUrl: "https://snowtrace.io",
merkleTreeHeight: 20,
emptyElement: "21663839004416932945382355908790599225266501822907911457504978515578255421292",
networkName: "Avalanche Mainnet",
deployedBlock: 4429818,
multicallContract: "0xcA11bde05977b3631167028862bE2a173976CA11",
routerContract: "0x0D5550d52428E7e3175bfc9550207e4ad3859b17",
echoContract: "0xa75BF2815618872f155b7C4B0C81bF990f5245E4",
offchainOracleContract: "0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8",
tornadoSubgraph: "tornadocash/avalanche-tornado-subgraph",
subgraphs: {},
rpcUrls: {
publicRpc: {
name: "Avalanche RPC",
url: "https://api.avax.network/ext/bc/C/rpc"
},
meowRPC: {
name: "Meow RPC",
url: "https://avax.meowrpc.com"
},
oneRPC: {
name: "OneRPC",
url: "https://1rpc.io/avax/c"
}
},
tokens: {
avax: {
instanceAddress: {
"10": "0x330bdFADE01eE9bF63C209Ee33102DD334618e0a",
"100": "0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD",
"500": "0xaf8d1839c3c67cf571aa74B5c12398d4901147B3"
},
symbol: "AVAX",
decimals: 18
}
},
relayerEnsSubdomain: "avalanche-tornado",
pollInterval: 10,
constants: {
NOTE_ACCOUNT_BLOCK: 4429813,
ENCRYPTED_NOTES_BLOCK: 4429813
}
},
[11155111 /* SEPOLIA */]: {
rpcCallRetryAttempt: 15,
gasPrices: {
instant: 2,
fast: 2,
standard: 2,
low: 2
},
nativeCurrency: "eth",
currencyName: "SepoliaETH",
explorerUrl: "https://sepolia.etherscan.io",
merkleTreeHeight: 20,
emptyElement: "21663839004416932945382355908790599225266501822907911457504978515578255421292",
networkName: "Ethereum Sepolia",
deployedBlock: 5594395,
multicallContract: "0xcA11bde05977b3631167028862bE2a173976CA11",
routerContract: "0x1572AFE6949fdF51Cb3E0856216670ae9Ee160Ee",
echoContract: "0xa75BF2815618872f155b7C4B0C81bF990f5245E4",
tornContract: "0x3AE6667167C0f44394106E197904519D808323cA",
governanceContract: "0xe5324cD7602eeb387418e594B87aCADee08aeCAD",
stakingRewardsContract: "0x6d0018890751Efd31feb8166711B16732E2b496b",
registryContract: "0x1428e5d2356b13778A13108b10c440C83011dfB8",
aggregatorContract: "0x4088712AC9fad39ea133cdb9130E465d235e9642",
reverseRecordsContract: "0xEc29700C0283e5Be64AcdFe8077d6cC95dE23C23",
tornadoSubgraph: "tornadocash/sepolia-tornado-subgraph",
subgraphs: {},
rpcUrls: {
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: {
instanceAddress: {
"0.1": "0x8C4A04d872a6C1BE37964A21ba3a138525dFF50b",
"1": "0x8cc930096B4Df705A007c4A039BDFA1320Ed2508",
"10": "0x8D10d506D29Fc62ABb8A290B99F66dB27Fc43585",
"100": "0x44c5C92ed73dB43888210264f0C8b36Fd68D8379"
},
symbol: "ETH",
decimals: 18
},
dai: {
instanceAddress: {
"100": "0x6921fd1a97441dd603a997ED6DDF388658daf754",
"1000": "0x50a637770F5d161999420F7d70d888DE47207145",
"10000": "0xecD649870407cD43923A816Cc6334a5bdf113621",
"100000": "0x73B4BD04bF83206B6e979BE2507098F92EDf4F90"
},
tokenAddress: "0xFF34B3d4Aee8ddCd6F9AFFFB6Fe49bD371b8a357",
tokenGasLimit: 7e4,
symbol: "DAI",
decimals: 18,
gasLimit: 7e5
}
},
relayerEnsSubdomain: "sepolia-tornado",
pollInterval: 15,
constants: {
GOVERNANCE_BLOCK: 5594395,
NOTE_ACCOUNT_BLOCK: 5594395,
ENCRYPTED_NOTES_BLOCK: 5594395,
MINING_BLOCK_TIME: 15
}
}
};
const enabledChains = Object.values(NetId).filter((n) => typeof n === "number");
exports.customConfig = {};
function addNetwork(newConfig) {
enabledChains.push(
...Object.keys(newConfig).map((netId) => Number(netId)).filter((netId) => !enabledChains.includes(netId))
);
exports.customConfig = __spreadValues$2(__spreadValues$2({}, exports.customConfig), newConfig);
}
function getNetworkConfig() {
const allConfig = __spreadValues$2(__spreadValues$2({}, defaultConfig), exports.customConfig);
return enabledChains.reduce((acc, curr) => {
acc[curr] = allConfig[curr];
return acc;
}, {});
}
function getConfig(netId) {
const allConfig = getNetworkConfig();
const chainConfig = allConfig[netId];
if (!chainConfig) {
const errMsg = `No config found for network ${netId}!`;
throw new Error(errMsg);
}
return chainConfig;
}
function getActiveTokens(config) {
const { tokens, disabledTokens } = config;
return Object.keys(tokens).filter((t) => !(disabledTokens == null ? void 0 : disabledTokens.includes(t)));
}
function getActiveTokenInstances(config) {
const { tokens, disabledTokens } = config;
return Object.entries(tokens).reduce((acc, [token, instances]) => {
if (!(disabledTokens == null ? void 0 : disabledTokens.includes(token))) {
acc[token] = instances;
}
return acc;
}, {});
}
function getInstanceByAddress(config, address) {
const { tokens, disabledTokens } = config;
for (const [currency, { instanceAddress }] of Object.entries(tokens)) {
if (disabledTokens == null ? void 0 : disabledTokens.includes(currency)) {
continue;
}
for (const [amount, instance] of Object.entries(instanceAddress)) {
if (instance === address) {
return {
amount,
currency
};
}
}
}
}
function getRelayerEnsSubdomains() {
const allConfig = getNetworkConfig();
return enabledChains.reduce((acc, chain) => {
acc[chain] = allConfig[chain].relayerEnsSubdomain;
return acc;
}, {});
}
const addressType = { type: "string", pattern: "^0x[a-fA-F0-9]{40}$" };
const bnType = { type: "string", BN: true };
const statusSchema = {
type: "object",
properties: {
rewardAccount: addressType,
gasPrices: {
type: "object",
properties: {
fast: { type: "number" },
additionalProperties: { type: "number" }
},
required: ["fast"]
},
netId: { type: "integer" },
tornadoServiceFee: { type: "number", maximum: 20, minimum: 0 },
latestBlock: { type: "number" },
version: { type: "string" },
health: {
type: "object",
properties: {
status: { const: "true" },
error: { type: "string" }
},
required: ["status"]
},
currentQueue: { type: "number" }
},
required: ["rewardAccount", "instances", "netId", "tornadoServiceFee", "version", "health"]
};
function getStatusSchema(netId, config) {
const { tokens, optionalTokens, disabledTokens, nativeCurrency } = config;
const schema = JSON.parse(JSON.stringify(statusSchema));
const instances = Object.keys(tokens).reduce(
(acc, token) => {
const { instanceAddress, tokenAddress, symbol, decimals, optionalInstances = [] } = tokens[token];
const amounts = Object.keys(instanceAddress);
const instanceProperties = {
type: "object",
properties: {
instanceAddress: {
type: "object",
properties: amounts.reduce((acc2, cur) => {
acc2[cur] = addressType;
return acc2;
}, {}),
required: amounts.filter((amount) => !optionalInstances.includes(amount))
},
decimals: { enum: [decimals] }
},
required: ["instanceAddress", "decimals"].concat(
tokenAddress ? ["tokenAddress"] : [],
symbol ? ["symbol"] : []
)
};
if (tokenAddress) {
instanceProperties.properties.tokenAddress = addressType;
}
if (symbol) {
instanceProperties.properties.symbol = { enum: [symbol] };
}
acc.properties[token] = instanceProperties;
if (!(optionalTokens == null ? void 0 : optionalTokens.includes(token)) && !(disabledTokens == null ? void 0 : disabledTokens.includes(token))) {
acc.required.push(token);
}
return acc;
},
{
type: "object",
properties: {},
required: []
}
);
schema.properties.instances = instances;
if (netId === NetId.MAINNET) {
const _tokens = Object.keys(tokens).filter((t) => t !== nativeCurrency);
const ethPrices = {
type: "object",
properties: _tokens.reduce((acc, token) => {
acc[token] = bnType;
return acc;
}, {})
// required: _tokens
};
schema.properties.ethPrices = ethPrices;
}
return schema;
}
const jobsSchema = {
type: "object",
properties: {
error: { type: "string" },
id: { type: "string" },
type: { type: "string" },
status: { type: "string" },
contract: { type: "string" },
proof: { type: "string" },
args: {
type: "array",
items: { type: "string" }
},
txHash: { type: "string" },
confirmations: { type: "number" },
failedReason: { type: "string" }
},
required: ["id", "status"]
};
const ajv = new Ajv({ allErrors: true });
ajv.addKeyword({
keyword: "BN",
// eslint-disable-next-line @typescript-eslint/no-explicit-any
validate: (schema, data) => {
try {
BigInt(data);
return true;
} catch (e) {
return false;
}
},
errors: true
});
var __defProp$1 = Object.defineProperty;
var __defProps$1 = Object.defineProperties;
var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues$1 = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp$1.call(b, prop))
__defNormalProp$1(a, prop, b[prop]);
if (__getOwnPropSymbols$1)
for (var prop of __getOwnPropSymbols$1(b)) {
if (__propIsEnum$1.call(b, prop))
__defNormalProp$1(a, prop, b[prop]);
}
return a;
};
var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
var __async$9 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
const MIN_FEE = 0.1;
const MAX_FEE = 0.9;
const MIN_STAKE_BALANCE = ethers.parseEther("500");
function calculateScore({ stakeBalance, tornadoServiceFee }) {
if (tornadoServiceFee < MIN_FEE) {
tornadoServiceFee = MIN_FEE;
} else if (tornadoServiceFee >= MAX_FEE) {
return BigInt(0);
}
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 || "0") * coefficientsMultiplier));
}
function getWeightRandom(weightsScores, random) {
for (let i = 0; i < weightsScores.length; i++) {
if (random < weightsScores[i]) {
return i;
}
random = random - weightsScores[i];
}
return Math.floor(Math.random() * weightsScores.length);
}
function getSupportedInstances(instanceList) {
const rawList = Object.values(instanceList).map(({ instanceAddress }) => {
return Object.values(instanceAddress);
}).flat();
return rawList.map((l) => ethers.getAddress(l));
}
function pickWeightedRandomRelayer(relayers) {
const weightsScores = relayers.map((el) => calculateScore(el));
const totalWeight = weightsScores.reduce((acc, curr) => {
return acc = acc + curr;
}, BigInt("0"));
const random = BigInt(Math.floor(Number(totalWeight) * Math.random()));
const weightRandomIndex = getWeightRandom(weightsScores, random);
return relayers[weightRandomIndex];
}
class RelayerClient {
constructor({ netId, config, fetchDataOptions: fetchDataOptions2 }) {
this.netId = netId;
this.config = config;
this.fetchDataOptions = fetchDataOptions2;
}
askRelayerStatus(_0) {
return __async$9(this, arguments, function* ({
hostname,
url,
relayerAddress
}) {
var _a, _b;
if (!url) {
url = `https://${!hostname.endsWith("/") ? hostname + "/" : hostname}`;
} else if (!url.endsWith("/")) {
url += "/";
}
const rawStatus = yield fetchData(`${url}status`, __spreadProps$1(__spreadValues$1({}, this.fetchDataOptions), {
headers: {
"Content-Type": "application/json, application/x-www-form-urlencoded"
},
timeout: ((_a = this.fetchDataOptions) == null ? void 0 : _a.torPort) ? 1e4 : 3e3,
maxRetry: ((_b = this.fetchDataOptions) == null ? void 0 : _b.torPort) ? 2 : 0
}));
const statusValidator = ajv.compile(getStatusSchema(this.netId, this.config));
if (!statusValidator(rawStatus)) {
throw new Error("Invalid status schema");
}
const status = __spreadProps$1(__spreadValues$1({}, rawStatus), {
url
});
if (status.currentQueue > 5) {
throw new Error("Withdrawal queue is overloaded");
}
if (status.netId !== this.netId) {
throw new Error("This relayer serves a different network");
}
if (relayerAddress && this.netId === NetId.MAINNET && status.rewardAccount !== relayerAddress) {
throw new Error("The Relayer reward address must match registered address");
}
return status;
});
}
filterRelayer(relayer) {
return __async$9(this, null, function* () {
var _a;
const hostname = relayer.hostnames[this.netId];
const { ensName, relayerAddress } = relayer;
if (!hostname) {
return;
}
try {
const status = yield this.askRelayerStatus({ hostname, relayerAddress });
return {
netId: status.netId,
url: status.url,
hostname,
ensName,
relayerAddress,
rewardAccount: ethers.getAddress(status.rewardAccount),
instances: getSupportedInstances(status.instances),
stakeBalance: relayer.stakeBalance,
gasPrice: (_a = status.gasPrices) == null ? void 0 : _a.fast,
ethPrices: status.ethPrices,
currentQueue: status.currentQueue,
tornadoServiceFee: status.tornadoServiceFee
};
} catch (err) {
return {
hostname,
relayerAddress,
errorMessage: err.message,
hasError: true
};
}
});
}
getValidRelayers(relayers) {
return __async$9(this, null, function* () {
const invalidRelayers = [];
const validRelayers = (yield Promise.all(relayers.map((relayer) => this.filterRelayer(relayer)))).filter((r) => {
if (!r) {
return false;
}
if (r.hasError) {
invalidRelayers.push(r);
return false;
}
return true;
});
return {
validRelayers,
invalidRelayers
};
});
}
pickWeightedRandomRelayer(relayers) {
return pickWeightedRandomRelayer(relayers);
}
tornadoWithdraw(_0) {
return __async$9(this, arguments, function* ({ contract, proof, args }) {
const { url } = this.selectedRelayer;
const withdrawResponse = yield fetchData(`${url}v1/tornadoWithdraw`, __spreadProps$1(__spreadValues$1({}, this.fetchDataOptions), {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
contract,
proof,
args
})
}));
const { id, error } = withdrawResponse;
if (error) {
throw new Error(error);
}
let relayerStatus;
const jobUrl = `${url}v1/jobs/${id}`;
console.log(`Job submitted: ${jobUrl}
`);
while (!relayerStatus || !["FAILED", "CONFIRMED"].includes(relayerStatus)) {
const jobResponse = yield fetchData(jobUrl, __spreadProps$1(__spreadValues$1({}, this.fetchDataOptions), {
method: "GET",
headers: {
"Content-Type": "application/json"
}
}));
if (jobResponse.error) {
throw new Error(error);
}
const jobValidator = ajv.compile(jobsSchema);
if (!jobValidator(jobResponse)) {
const errMsg = `${jobUrl} has an invalid job response`;
throw new Error(errMsg);
}
const { status, txHash, confirmations, failedReason } = jobResponse;
if (relayerStatus !== status) {
if (status === "FAILED") {
const errMsg = `Job ${status}: ${jobUrl} failed reason: ${failedReason}`;
throw new Error(errMsg);
} else if (status === "SENT") {
console.log(`Job ${status}: ${jobUrl}, txhash: ${txHash}
`);
} else if (status === "MINED") {
console.log(`Job ${status}: ${jobUrl}, txhash: ${txHash}, confirmations: ${confirmations}
`);
} else if (status === "CONFIRMED") {
console.log(`Job ${status}: ${jobUrl}, txhash: ${txHash}, confirmations: ${confirmations}
`);
} else {
console.log(`Job ${status}: ${jobUrl}
`);
}
relayerStatus = status;
}
yield sleep(3e3);
}
});
}
}
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __reflectGet = Reflect.get;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
var __async$8 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
const DEPOSIT = "deposit";
const WITHDRAWAL = "withdrawal";
class BaseEventsService {
constructor({
netId,
provider,
graphApi,
subgraphName,
contract,
type = "",
deployedBlock = 0,
fetchDataOptions: fetchDataOptions2
}) {
this.netId = netId;
this.provider = provider;
this.graphApi = graphApi;
this.subgraphName = subgraphName;
this.fetchDataOptions = fetchDataOptions2;
this.contract = contract;
this.type = type;
this.deployedBlock = deployedBlock;
this.batchEventsService = new BatchEventsService({
provider,
contract,
onProgress: this.updateEventProgress
});
}
getInstanceName() {
return "";
}
getType() {
return this.type || "";
}
getGraphMethod() {
return "";
}
getGraphParams() {
return {
graphApi: this.graphApi || "",
subgraphName: this.subgraphName || "",
fetchDataOptions: this.fetchDataOptions,
onProgress: this.updateGraphProgress
};
}
/* eslint-disable @typescript-eslint/no-unused-vars */
updateEventProgress({ percentage, type, fromBlock, toBlock, count }) {
}
updateBlockProgress({ percentage, currentIndex, totalIndex }) {
}
updateTransactionProgress({ percentage, currentIndex, totalIndex }) {
}
updateGraphProgress({ type, fromBlock, toBlock, count }) {
}
/* eslint-enable @typescript-eslint/no-unused-vars */
formatEvents(events) {
return __async$8(this, null, function* () {
return yield new Promise((resolve) => resolve(events));
});
}
/**
* Get saved or cached events
*/
getEventsFromDB() {
return __async$8(this, null, function* () {
return {
events: [],
lastBlock: null
};
});
}
/**
* Events from remote cache (Either from local cache, CDN, or from IPFS)
*/
getEventsFromCache() {
return __async$8(this, null, function* () {
return {
events: [],
lastBlock: null,
fromCache: true
};
});
}
getSavedEvents() {
return __async$8(this, null, function* () {
let cachedEvents = yield this.getEventsFromDB();
if (!cachedEvents || !cachedEvents.events.length) {
cachedEvents = yield this.getEventsFromCache();
}
return cachedEvents;
});
}
/**
* Get latest events
*/
getEventsFromGraph(_0) {
return __async$8(this, arguments, function* ({
fromBlock,
methodName = ""
}) {
if (!this.graphApi || !this.subgraphName) {
return {
events: [],
lastBlock: fromBlock
};
}
const { events, lastSyncBlock } = yield graph[methodName || this.getGraphMethod()](__spreadValues({
fromBlock
}, this.getGraphParams()));
return {
events,
lastBlock: lastSyncBlock
};
});
}
getEventsFromRpc(_0) {
return __async$8(this, arguments, function* ({
fromBlock,
toBlock
}) {
try {
if (!toBlock) {
toBlock = yield this.provider.getBlockNumber();
}
if (fromBlock >= toBlock) {
return {
events: [],
lastBlock: toBlock
};
}
this.updateEventProgress({ percentage: 0, type: this.getType() });
const events = yield this.formatEvents(
yield this.batchEventsService.getBatchEvents({ fromBlock, toBlock, type: this.getType() })
);
return {
events,
lastBlock: toBlock
};
} catch (err) {
console.log(err);
return {
events: [],
lastBlock: fromBlock
};
}
});
}
getLatestEvents(_0) {
return __async$8(this, arguments, function* ({ fromBlock }) {
const graphEvents = yield this.getEventsFromGraph({ fromBlock });
const lastSyncBlock = graphEvents.lastBlock && graphEvents.lastBlock >= fromBlock ? graphEvents.lastBlock : fromBlock;
const rpcEvents = yield this.getEventsFromRpc({ fromBlock: lastSyncBlock });
return {
events: [...graphEvents.events, ...rpcEvents.events],
lastBlock: rpcEvents.lastBlock
};
});
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
validateEvents({ events, lastBlock }) {
}
/**
* Handle saving events
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
saveEvents(_0) {
return __async$8(this, arguments, function* ({ events, lastBlock }) {
});
}
/**
* Trigger saving and receiving latest events
*/
updateEvents() {
return __async$8(this, null, function* () {
var _a;
const savedEvents = yield this.getSavedEvents();
let fromBlock = this.deployedBlock;
if (savedEvents && savedEvents.lastBlock) {
fromBlock = savedEvents.lastBlock + 1;
}
const newEvents = yield this.getLatestEvents({ fromBlock });
const eventSet = /* @__PURE__ */ new Set();
const allEvents = [...savedEvents.events, ...newEvents.events].sort((a, b) => {
if (a.blockNumber === b.blockNumber) {
return a.logIndex - b.logIndex;
}
return a.blockNumber - b.blockNumber;
}).filter(({ transactionHash, logIndex }) => {
const eventKey = `${transactionHash}_${logIndex}`;
const hasEvent = eventSet.has(eventKey);
eventSet.add(eventKey);
return !hasEvent;
});
const lastBlock = newEvents.lastBlock || ((_a = allEvents[allEvents.length - 1]) == null ? void 0 : _a.blockNumber);
this.validateEvents({ events: allEvents, lastBlock });
if (savedEvents.fromCache || newEvents.events.length) {
yield this.saveEvents({ events: allEvents, lastBlock });
}
return {
events: allEvents,
lastBlock
};
});
}
}
class BaseTornadoService extends BaseEventsService {
constructor({
netId,
provider,
graphApi,
subgraphName,
Tornado,
type,
amount,
currency,
deployedBlock,
fetchDataOptions: fetchDataOptions2
}) {
super({ netId, provider, graphApi, subgraphName, contract: Tornado, type, deployedBlock, fetchDataOptions: fetchDataOptions2 });
this.amount = amount;
this.currency = currency;
this.batchTransactionService = new BatchTransactionService({
provider,
onProgress: this.updateTransactionProgress
});
this.batchBlockService = new BatchBlockService({
provider,
onProgress: this.updateBlockProgress
});
}
getInstanceName() {
return `${this.getType().toLowerCase()}s_${this.netId}_${this.currency}_${this.amount}`;
}
getGraphMethod() {
return `getAll${this.getType()}s`;
}
getGraphParams() {
return {
graphApi: this.graphApi || "",
subgraphName: this.subgraphName || "",
amount: this.amount,
currency: this.currency,
fetchDataOptions: this.fetchDataOptions,
onProgress: this.updateGraphProgress
};
}
formatEvents(events) {
return __async$8(this, null, function* () {
const type = this.getType().toLowerCase();
if (type === DEPOSIT) {
const formattedEvents = events.map(({ blockNumber, index: logIndex, transactionHash, args }) => {
const { commitment, leafIndex, timestamp } = args;
return {
blockNumber,
logIndex,
transactionHash,
commitment,
leafIndex: Number(leafIndex),
timestamp: Number(timestamp)
};
});
const txs = yield this.batchTransactionService.getBatchTransactions([
...new Set(formattedEvents.map(({ transactionHash }) => transactionHash))
]);
return formattedEvents.map((event) => {
const { from } = txs.find(({ hash }) => hash === event.transactionHash);
return __spreadProps(__spreadValues({}, event), {
from
});
});
} else {
const formattedEvents = events.map(({ blockNumber, index: logIndex, transactionHash, args }) => {
const { nullifierHash, to, fee } = args;
return {
blockNumber,
logIndex,
transactionHash,
nullifierHash: String(nullifierHash),
to: ethers.getAddress(to),
fee: String(fee)
};
});
const blocks = yield this.batchBlockService.getBatchBlocks([
...new Set(formattedEvents.map(({ blockNumber }) => blockNumber))
]);
return formattedEvents.map((event) => {
const { timestamp } = blocks.find(({ number }) => number === event.blockNumber);
return __spreadProps(__spreadValues({}, event), {
timestamp
});
});
}
});
}
validateEvents({ events }) {
if (events.length && this.getType().toLowerCase() === DEPOSIT) {
const lastEvent = events[events.length - 1];
if (lastEvent.leafIndex !== events.length - 1) {
const errMsg = `Deposit events invalid wants ${events.length - 1} leafIndex have ${lastEvent.leafIndex}`;
throw new Error(errMsg);
}
}
}
}
class BaseEchoService extends BaseEventsService {
constructor({
netId,
provider,
graphApi,
subgraphName,
Echoer,
deployedBlock,
fetchDataOptions: fetchDataOptions2
}) {
super({ netId, provider, graphApi, subgraphName, contract: Echoer, deployedBlock, fetchDataOptions: fetchDataOptions2 });
}
getInstanceName() {
return `echo_${this.netId}`;
}
getType() {
return "Echo";
}
getGraphMethod() {
return "getAllGraphEchoEvents";
}
formatEvents(events) {
return __async$8(this, null, function* () {
return events.map(({ blockNumber, index: logIndex, transactionHash, args }) => {
const { who, data } = args;
if (who && data) {
const eventObjects = {
blockNumber,
logIndex,
transactionHash
};
return __spreadProps(__spreadValues({}, eventObjects), {
address: who,
encryptedAccount: data
});
}
}).filter((e) => e);
});
}
getEventsFromGraph(_0) {
return __async$8(this, arguments, function* ({ fromBlock }) {
if (!this.graphApi || this.graphApi.includes("api.thegraph.com")) {
return {
events: [],
lastBlock: fromBlock
};
}
return __superGet(BaseEchoService.prototype, this, "getEventsFromGraph").call(this, { fromBlock });
});
}
}
class BaseEncryptedNotesService extends BaseEventsService {
constructor({
netId,
provider,
graphApi,
subgraphName,
Router,
deployedBlock,
fetchDataOptions: fetchDataOptions2
}) {
super({ netId, provider, graphApi, subgraphName, contract: Router, deployedBlock, fetchDataOptions: fetchDataOptions2 });
}
getInstanceName() {
return `encrypted_notes_${this.netId}`;
}
getType() {
return "EncryptedNote";
}
getGraphMethod() {
return "getAllEncryptedNotes";
}
formatEvents(events) {
return __async$8(this, null, function* () {
return events.map(({ blockNumber, index: logIndex, transactionHash, args }) => {
const { encryptedNote } = args;
if (encryptedNote && encryptedNote !== "0x") {
const eventObjects = {
blockNumber,
logIndex,
transactionHash
};
return __spreadProps(__spreadValues({}, eventObjects), {
encryptedNote
});
}
}).filter((e) => e);
});
}
}
class BaseGovernanceService extends BaseEventsService {
constructor({
netId,
provider,
graphApi,
subgraphName,
Governance,
deployedBlock,
fetchDataOptions: fetchDataOptions2
}) {
super({ netId, provider, graphApi, subgraphName, contract: Governance, deployedBlock, fetchDataOptions: fetchDataOptions2 });
this.batchTransactionService = new BatchTransactionService({
provider,
onProgress: this.updateTransactionProgress
});
}
getInstanceName() {
return `governance_${this.netId}`;
}
getType() {
return "*";
}
getGraphMethod() {
return "getAllGovernanceEvents";
}
formatEvents(events) {
return __async$8(this, null, function* () {
const proposalEvents = [];
const votedEvents = [];
const delegatedEvents = [];
const undelegatedEvents = [];
events.forEach(({ blockNumber, index: logIndex, transactionHash, args, eventName: event }) => {
const eventObjects = {
blockNumber,
logIndex,
transactionHash,
event
};
if (event === "ProposalCreated") {
const { id, proposer, target, startTime, endTime, description } = args;
proposalEvents.push(__spreadProps(__spreadValues({}, eventObjects), {
id: Number(id),
proposer,
target,
startTime: Number(startTime),
endTime: Number(endTime),
description
}));
}
if (event === "Voted") {
const { proposalId, voter, support, votes } = args;
votedEvents.push(__spreadProps(__spreadValues({}, eventObjects), {
proposalId: Number(proposalId),
voter,
support,
votes,
from: "",
input: ""
}));
}
if (event === "Delegated") {
const { account, to: delegateTo } = args;
delegatedEvents.push(__spreadProps(__spreadValues({}, eventObjects), {
account,
delegateTo
}));
}
if (event === "Undelegated") {
const { account, from: delegateFrom } = args;
undelegatedEvents.push(__spreadProps(__spreadValues({}, eventObjects), {
account,
delegateFrom
}));
}
});
if (votedEvents.length) {
this.updateTransactionProgress({ percentage: 0 });
const txs = yield this.batchTransactionService.getBatchTransactions([
...new Set(votedEvents.map(({ transactionHash }) => transactionHash))
]);
votedEvents.forEach((event, index) => {
let { data: input, from } = txs.find((t) => t.hash === event.transactionHash);
if (!input || input.length > 2048) {
input = "";
}
votedEvents[index].from = from;
votedEvents[index].input = input;
});
}
return [...proposalEvents, ...votedEvents, ...delegatedEvents, ...undelegatedEvents];
});
}
getEventsFromGraph(_0) {
return __async$8(this, arguments, function* ({ fromBlock }) {
if (!this.graphApi || !this.subgraphName || this.graphApi.includes("api.thegraph.com")) {
return {
events: [],
lastBlock: fromBlock
};
}
return __superGet(BaseGovernanceService.prototype, this, "getEventsFromGraph").call(this, { fromBlock });
});
}
}
function getTovarishNetworks(registryService, relayers) {
return __async$8(this, null, function* () {
yield Promise.all(
relayers.filter((r) => r.tovarishUrl).map((relayer) => __async$8(this, null, function* () {
var _a, _b;
try {
relayer.tovarishNetworks = yield fetchData(relayer.tovarishUrl, __spreadProps(__spreadValues({}, registryService.fetchDataOptions), {
headers: {
"Content-Type": "application/json"
},
timeout: ((_a = registryService.fetchDataOptions) == null ? void 0 : _a.torPort) ? 1e4 : 3e3,
maxRetry: ((_b = registryService.fetchDataOptions) == null ? void 0 : _b.torPort) ? 2 : 0
}));
} catch (e) {
relayer.tovarishNetworks = [];
}
}))
);
});
}
class BaseRegistryService extends BaseEventsService {
constructor({
netId,
provider,
graphApi,
subgraphName,
RelayerRegistry,
Aggregator,
relayerEnsSubdomains,
deployedBlock,
fetchDataOptions: fetchDataOptions2
}) {
super({ netId, provider, graphApi, subgraphName, contract: RelayerRegistry, deployedBlock, fetchDataOptions: fetchDataOptions2 });
this.Aggregator = Aggregator;
this.relayerEnsSubdomains = relayerEnsSubdomains;
this.updateInterval = 86400;
}
getInstanceName() {
return `registered_${this.netId}`;
}
// Name of type used for events
getType() {
return "RelayerRegistered";
}
// Name of method used for graph
getGraphMethod() {
return "getAllRegisters";
}
formatEvents(events) {
return __async$8(this, null, function* () {
return events.map(({ blockNumber, index: logIndex, transactionHash, args }) => {
const eventObjects = {
blockNumber,
logIndex,
transactionHash
};
return __spreadProps(__spreadValues({}, eventObjects), {
ensName: args.ensName,
relayerAddress: args.relayerAddress
});
});
});
}
/**
* Get saved or cached relayers
*/
getRelayersFromDB() {
return __async$8(this, null, function* () {
return {
timestamp: 0,
relayers: []
};
});
}
/**
* Relayers from remote cache (Either from local cache, CDN, or from IPFS)
*/
getRelayersFromCache() {
return __async$8(this, null, function* () {
return {
timestamp: 0,
relayers: [],
fromCache: true
};
});
}
getSavedRelayers() {
return __async$8(this, null, function* () {
let cachedRelayers = yield this.getRelayersFromDB();
if (!cachedRelayers || !cachedRelayers.relayers.length) {
cachedRelayers = yield this.getRelayersFromCache();
}
return cachedRelayers;
});
}
getLatestRelayers() {
return __async$8(this, null, function* () {
const registerEvents = (yield this.updateEvents()).events;
const subdomains = Object.values(this.relayerEnsSubdomains);
const registerSet = /* @__PURE__ */ new Set();
const uniqueRegisters = registerEvents.filter(({ ensName }) => {
if (!registerSet.has(ensName)) {
registerSet.add(ensName);
return true;
}
return false;
});
const relayerNameHashes = uniqueRegisters.map((r) => ethers.namehash(r.ensName));
const [relayersData, timestamp] = yield Promise.all([
this.Aggregator.relayersData.staticCall(relayerNameHashes, subdomains.concat("tovarish-relayer")),
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];
let tovarishUrl = void 0;
const hostnames = records.reduce((acc, record, recordIndex) => {
if (record) {
if (recordIndex === records.length - 1) {
tovarishUrl = record;
return acc;
}
acc[Number(Object.keys(this.relayerEnsSubdomains)[recordIndex])] = record;
}
return acc;
}, {});
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: ethers.formatEther(stakeBalance),
hostnames,
tovarishUrl
};
}
}).filter((r) => r);
yield getTovarishNetworks(this, relayers);
return {
timestamp,
relayers
};
});
}
/**
* Handle saving relayers
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
saveRelayers(_0) {
return __async$8(this, arguments, function* ({ timestamp, relayers }) {
});
}
/**
* Get cached or latest relayer and save to local
*/
updateRelayers() {
return __async$8(this, null, function* () {
let { timestamp, relayers, fromCache } = yield this.getSavedRelayers();
let shouldSave = fromCache != null ? fromCache : false;
if (!relayers.length || timestamp + this.updateInterval < Math.floor(Date.now() / 1e3)) {
console.log("\nUpdating relayers from registry\n");
({ timestamp, relayers } = yield this.getLatestRelayers());
shouldSave = true;
}
if (shouldSave) {
yield this.saveRelayers({ timestamp, relayers });
}
return { timestamp, relayers };
});
}
}
const _abi$5 = [
{
constant: true,
inputs: [
{
internalType: "bytes4",
name: "interfaceID",
type: "bytes4"
}
],
name: "supportsInterface",
outputs: [
{
internalType: "bool",
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "pure",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "string",
name: "key",
type: "string"
},
{
internalType: "string",
name: "value",
type: "string"
}
],
name: "setText",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "bytes4",
name: "interfaceID",
type: "bytes4"
}
],
name: "interfaceImplementer",
outputs: [
{
internalType: "address",
name: "",
type: "address"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "uint256",
name: "contentTypes",
type: "uint256"
}
],
name: "ABI",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
},
{
internalType: "bytes",
name: "",
type: "bytes"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "bytes32",
name: "x",
type: "bytes32"
},
{
internalType: "bytes32",
name: "y",
type: "bytes32"
}
],
name: "setPubkey",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "bytes",
name: "hash",
type: "bytes"
}
],
name: "setContenthash",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
}
],
name: "addr",
outputs: [
{
internalType: "address",
name: "",
type: "address"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "address",
name: "target",
type: "address"
},
{
internalType: "bool",
name: "isAuthorised",
type: "bool"
}
],
name: "setAuthorisation",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "string",
name: "key",
type: "string"
}
],
name: "text",
outputs: [
{
internalType: "string",
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "uint256",
name: "contentType",
type: "uint256"
},
{
internalType: "bytes",
name: "data",
type: "bytes"
}
],
name: "setABI",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
}
],
name: "name",
outputs: [
{
internalType: "string",
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "string",
name: "name",
type: "string"
}
],
name: "setName",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "uint256",
name: "coinType",
type: "uint256"
},
{
internalType: "bytes",
name: "a",
type: "bytes"
}
],
name: "setAddr",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
}
],
name: "contenthash",
outputs: [
{
internalType: "bytes",
name: "",
type: "bytes"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
}
],
name: "pubkey",
outputs: [
{
internalType: "bytes32",
name: "x",
type: "bytes32"
},
{
internalType: "bytes32",
name: "y",
type: "bytes32"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "address",
name: "a",
type: "address"
}
],
name: "setAddr",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "bytes4",
name: "interfaceID",
type: "bytes4"
},
{
internalType: "address",
name: "implementer",
type: "address"
}
],
name: "setInterface",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [
{
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
internalType: "uint256",
name: "coinType",
type: "uint256"
}
],
name: "addr",
outputs: [
{
internalType: "bytes",
name: "",
type: "bytes"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [
{
internalType: "bytes32",
name: "",
type: "bytes32"
},
{
internalType: "address",
name: "",
type: "address"
},
{
internalType: "address",
name: "",
type: "address"
}
],
name: "authorisations",
outputs: [
{
internalType: "bool",
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "contract ENS",
name: "_ens",
type: "address"
}
],
payable: false,
stateMutability: "nonpayable",
type: "constructor"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
indexed: true,
internalType: "address",
name: "owner",
type: "address"
},
{
indexed: true,
internalType: "address",
name: "target",
type: "address"
},
{
indexed: false,
internalType: "bool",
name: "isAuthorised",
type: "bool"
}
],
name: "AuthorisationChanged",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
indexed: false,
internalType: "string",
name: "indexedKey",
type: "string"
},
{
indexed: false,
internalType: "string",
name: "key",
type: "string"
}
],
name: "TextChanged",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
indexed: false,
internalType: "bytes32",
name: "x",
type: "bytes32"
},
{
indexed: false,
internalType: "bytes32",
name: "y",
type: "bytes32"
}
],
name: "PubkeyChanged",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
indexed: false,
internalType: "string",
name: "name",
type: "string"
}
],
name: "NameChanged",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
indexed: true,
internalType: "bytes4",
name: "interfaceID",
type: "bytes4"
},
{
indexed: false,
internalType: "address",
name: "implementer",
type: "address"
}
],
name: "InterfaceChanged",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
indexed: false,
internalType: "bytes",
name: "hash",
type: "bytes"
}
],
name: "ContenthashChanged",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
indexed: false,
internalType: "address",
name: "a",
type: "address"
}
],
name: "AddrChanged",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
indexed: false,
internalType: "uint256",
name: "coinType",
type: "uint256"
},
{
indexed: false,
internalType: "bytes",
name: "newAddress",
type: "bytes"
}
],
name: "AddressChanged",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "node",
type: "bytes32"
},
{
indexed: true,
internalType: "uint256",
name: "contentType",
type: "uint256"
}
],
name: "ABIChanged",
type: "event"
}
];
class ENS__factory {
static createInterface() {
return new ethers.Interface(_abi$5);
}
static connect(address, runner) {
return new ethers.Contract(address, _abi$5, runner);
}
}
ENS__factory.abi = _abi$5;
const _abi$4 = [
{
constant: true,
inputs: [],
name: "totalSupply",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [],
name: "_totalSupply",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [
{
internalType: "address",
name: "who",
type: "address"
}
],
name: "balanceOf",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [],
name: "name",
outputs: [
{
internalType: "string",
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [],
name: "symbol",
outputs: [
{
internalType: "string",
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [],
name: "decimals",
outputs: [
{
internalType: "uint8",
name: "",
type: "uint8"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "address",
name: "to",
type: "address"
},
{
internalType: "uint256",
name: "value",
type: "uint256"
}
],
name: "transfer",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "owner",
type: "address"
},
{
indexed: true,
internalType: "address",
name: "spender",
type: "address"
},
{
indexed: false,
internalType: "uint256",
name: "value",
type: "uint256"
}
],
name: "Approval",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "from",
type: "address"
},
{
indexed: true,
internalType: "address",
name: "to",
type: "address"
},
{
indexed: false,
internalType: "uint256",
name: "value",
type: "uint256"
}
],
name: "Transfer",
type: "event"
},
{
constant: true,
inputs: [
{
internalType: "address",
name: "owner",
type: "address"
},
{
internalType: "address",
name: "spender",
type: "address"
}
],
name: "allowance",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "address",
name: "from",
type: "address"
},
{
internalType: "address",
name: "to",
type: "address"
},
{
internalType: "uint256",
name: "value",
type: "uint256"
}
],
name: "transferFrom",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: false,
inputs: [
{
internalType: "address",
name: "spender",
type: "address"
},
{
internalType: "uint256",
name: "value",
type: "uint256"
}
],
name: "approve",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "address",
name: "owner",
type: "address"
}
],
name: "nonces",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "address",
name: "owner",
type: "address"
},
{
internalType: "address",
name: "spender",
type: "address"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
},
{
internalType: "uint256",
name: "deadline",
type: "uint256"
},
{
internalType: "uint8",
name: "v",
type: "uint8"
},
{
internalType: "bytes32",
name: "r",
type: "bytes32"
},
{
internalType: "bytes32",
name: "s",
type: "bytes32"
}
],
name: "permit",
outputs: [],
stateMutability: "nonpayable",
type: "function"
}
];
class ERC20__factory {
static createInterface() {
return new ethers.Interface(_abi$4);
}
static connect(address, runner) {
return new ethers.Contract(address, _abi$4, runner);
}
}
ERC20__factory.abi = _abi$4;
const _abi$3 = [
{
inputs: [
{
components: [
{
internalType: "address",
name: "target",
type: "address"
},
{
internalType: "bytes",
name: "callData",
type: "bytes"
}
],
internalType: "struct Multicall3.Call[]",
name: "calls",
type: "tuple[]"
}
],
name: "aggregate",
outputs: [
{
internalType: "uint256",
name: "blockNumber",
type: "uint256"
},
{
internalType: "bytes[]",
name: "returnData",
type: "bytes[]"
}
],
stateMutability: "payable",
type: "function"
},
{
inputs: [
{
components: [
{
internalType: "address",
name: "target",
type: "address"
},
{
internalType: "bool",
name: "allowFailure",
type: "bool"
},
{
internalType: "bytes",
name: "callData",
type: "bytes"
}
],
internalType: "struct Multicall3.Call3[]",
name: "calls",
type: "tuple[]"
}
],
name: "aggregate3",
outputs: [
{
components: [
{
internalType: "bool",
name: "success",
type: "bool"
},
{
internalType: "bytes",
name: "returnData",
type: "bytes"
}
],
internalType: "struct Multicall3.Result[]",
name: "returnData",
type: "tuple[]"
}
],
stateMutability: "payable",
type: "function"
},
{
inputs: [
{
components: [
{
internalType: "address",
name: "target",
type: "address"
},
{
internalType: "bool",
name: "allowFailure",
type: "bool"
},
{
internalType: "uint256",
name: "value",
type: "uint256"
},
{
internalType: "bytes",
name: "callData",
type: "bytes"
}
],
internalType: "struct Multicall3.Call3Value[]",
name: "calls",
type: "tuple[]"
}
],
name: "aggregate3Value",
outputs: [
{
components: [
{
internalType: "bool",
name: "success",
type: "bool"
},
{
internalType: "bytes",
name: "returnData",
type: "bytes"
}
],
internalType: "struct Multicall3.Result[]",
name: "returnData",
type: "tuple[]"
}
],
stateMutability: "payable",
type: "function"
},
{
inputs: [
{
components: [
{
internalType: "address",
name: "target",
type: "address"
},
{
internalType: "bytes",
name: "callData",
type: "bytes"
}
],
internalType: "struct Multicall3.Call[]",
name: "calls",
type: "tuple[]"
}
],
name: "blockAndAggregate",
outputs: [
{
internalType: "uint256",
name: "blockNumber",
type: "uint256"
},
{
internalType: "bytes32",
name: "blockHash",
type: "bytes32"
},
{
components: [
{
internalType: "bool",
name: "success",
type: "bool"
},
{
internalType: "bytes",
name: "returnData",
type: "bytes"
}
],
internalType: "struct Multicall3.Result[]",
name: "returnData",
type: "tuple[]"
}
],
stateMutability: "payable",
type: "function"
},
{
inputs: [],
name: "getBasefee",
outputs: [
{
internalType: "uint256",
name: "basefee",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "uint256",
name: "blockNumber",
type: "uint256"
}
],
name: "getBlockHash",
outputs: [
{
internalType: "bytes32",
name: "blockHash",
type: "bytes32"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "getBlockNumber",
outputs: [
{
internalType: "uint256",
name: "blockNumber",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "getChainId",
outputs: [
{
internalType: "uint256",
name: "chainid",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "getCurrentBlockCoinbase",
outputs: [
{
internalType: "address",
name: "coinbase",
type: "address"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "getCurrentBlockDifficulty",
outputs: [
{
internalType: "uint256",
name: "difficulty",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "getCurrentBlockGasLimit",
outputs: [
{
internalType: "uint256",
name: "gaslimit",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "getCurrentBlockTimestamp",
outputs: [
{
internalType: "uint256",
name: "timestamp",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "address",
name: "addr",
type: "address"
}
],
name: "getEthBalance",
outputs: [
{
internalType: "uint256",
name: "balance",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "getLastBlockHash",
outputs: [
{
internalType: "bytes32",
name: "blockHash",
type: "bytes32"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "bool",
name: "requireSuccess",
type: "bool"
},
{
components: [
{
internalType: "address",
name: "target",
type: "address"
},
{
internalType: "bytes",
name: "callData",
type: "bytes"
}
],
internalType: "struct Multicall3.Call[]",
name: "calls",
type: "tuple[]"
}
],
name: "tryAggregate",
outputs: [
{
components: [
{
internalType: "bool",
name: "success",
type: "bool"
},
{
internalType: "bytes",
name: "returnData",
type: "bytes"
}
],
internalType: "struct Multicall3.Result[]",
name: "returnData",
type: "tuple[]"
}
],
stateMutability: "payable",
type: "function"
},
{
inputs: [
{
internalType: "bool",
name: "requireSuccess",
type: "bool"
},
{
components: [
{
internalType: "address",
name: "target",
type: "address"
},
{
internalType: "bytes",
name: "callData",
type: "bytes"
}
],
internalType: "struct Multicall3.Call[]",
name: "calls",
type: "tuple[]"
}
],
name: "tryBlockAndAggregate",
outputs: [
{
internalType: "uint256",
name: "blockNumber",
type: "uint256"
},
{
internalType: "bytes32",
name: "blockHash",
type: "bytes32"
},
{
components: [
{
internalType: "bool",
name: "success",
type: "bool"
},
{
internalType: "bytes",
name: "returnData",
type: "bytes"
}
],
internalType: "struct Multicall3.Result[]",
name: "returnData",
type: "tuple[]"
}
],
stateMutability: "payable",
type: "function"
}
];
class Multicall__factory {
static createInterface() {
return new ethers.Interface(_abi$3);
}
static connect(address, runner) {
return new ethers.Contract(address, _abi$3, runner);
}
}
Multicall__factory.abi = _abi$3;
const _abi$2 = [
{
inputs: [
{
internalType: "contract MultiWrapper",
name: "_multiWrapper",
type: "address"
},
{
internalType: "contract IOracle[]",
name: "existingOracles",
type: "address[]"
},
{
internalType: "enum OffchainOracle.OracleType[]",
name: "oracleTypes",
type: "uint8[]"
},
{
internalType: "contract IERC20[]",
name: "existingConnectors",
type: "address[]"
},
{
internalType: "contract IERC20",
name: "wBase",
type: "address"
},
{
internalType: "address",
name: "owner",
type: "address"
}
],
stateMutability: "nonpayable",
type: "constructor"
},
{
inputs: [],
name: "ArraysLengthMismatch",
type: "error"
},
{
inputs: [],
name: "ConnectorAlreadyAdded",
type: "error"
},
{
inputs: [],
name: "InvalidOracleTokenKind",
type: "error"
},
{
inputs: [],
name: "OracleAlreadyAdded",
type: "error"
},
{
inputs: [],
name: "SameTokens",
type: "error"
},
{
inputs: [],
name: "TooBigThreshold",
type: "error"
},
{
inputs: [],
name: "UnknownConnector",
type: "error"
},
{
inputs: [],
name: "UnknownOracle",
type: "error"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "contract IERC20",
name: "connector",
type: "address"
}
],
name: "ConnectorAdded",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "contract IERC20",
name: "connector",
type: "address"
}
],
name: "ConnectorRemoved",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "contract MultiWrapper",
name: "multiWrapper",
type: "address"
}
],
name: "MultiWrapperUpdated",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "contract IOracle",
name: "oracle",
type: "address"
},
{
indexed: false,
internalType: "enum OffchainOracle.OracleType",
name: "oracleType",
type: "uint8"
}
],
name: "OracleAdded",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "contract IOracle",
name: "oracle",
type: "address"
},
{
indexed: false,
internalType: "enum OffchainOracle.OracleType",
name: "oracleType",
type: "uint8"
}
],
name: "OracleRemoved",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "previousOwner",
type: "address"
},
{
indexed: true,
internalType: "address",
name: "newOwner",
type: "address"
}
],
name: "OwnershipTransferred",
type: "event"
},
{
inputs: [
{
internalType: "contract IERC20",
name: "connector",
type: "address"
}
],
name: "addConnector",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "contract IOracle",
name: "oracle",
type: "address"
},
{
internalType: "enum OffchainOracle.OracleType",
name: "oracleKind",
type: "uint8"
}
],
name: "addOracle",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [],
name: "connectors",
outputs: [
{
internalType: "contract IERC20[]",
name: "allConnectors",
type: "address[]"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "contract IERC20",
name: "srcToken",
type: "address"
},
{
internalType: "contract IERC20",
name: "dstToken",
type: "address"
},
{
internalType: "bool",
name: "useWrappers",
type: "bool"
}
],
name: "getRate",
outputs: [
{
internalType: "uint256",
name: "weightedRate",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "contract IERC20",
name: "srcToken",
type: "address"
},
{
internalType: "bool",
name: "useSrcWrappers",
type: "bool"
}
],
name: "getRateToEth",
outputs: [
{
internalType: "uint256",
name: "weightedRate",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "contract IERC20",
name: "srcToken",
type: "address"
},
{
internalType: "bool",
name: "useSrcWrappers",
type: "bool"
},
{
internalType: "contract IERC20[]",
name: "customConnectors",
type: "address[]"
},
{
internalType: "uint256",
name: "thresholdFilter",
type: "uint256"
}
],
name: "getRateToEthWithCustomConnectors",
outputs: [
{
internalType: "uint256",
name: "weightedRate",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "contract IERC20",
name: "srcToken",
type: "address"
},
{
internalType: "bool",
name: "useSrcWrappers",
type: "bool"
},
{
internalType: "uint256",
name: "thresholdFilter",
type: "uint256"
}
],
name: "getRateToEthWithThreshold",
outputs: [
{
internalType: "uint256",
name: "weightedRate",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "contract IERC20",
name: "srcToken",
type: "address"
},
{
internalType: "contract IERC20",
name: "dstToken",
type: "address"
},
{
internalType: "bool",
name: "useWrappers",
type: "bool"
},
{
internalType: "contract IERC20[]",
name: "customConnectors",
type: "address[]"
},
{
internalType: "uint256",
name: "thresholdFilter",
type: "uint256"
}
],
name: "getRateWithCustomConnectors",
outputs: [
{
internalType: "uint256",
name: "weightedRate",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "contract IERC20",
name: "srcToken",
type: "address"
},
{
internalType: "contract IERC20",
name: "dstToken",
type: "address"
},
{
internalType: "bool",
name: "useWrappers",
type: "bool"
},
{
internalType: "uint256",
name: "thresholdFilter",
type: "uint256"
}
],
name: "getRateWithThreshold",
outputs: [
{
internalType: "uint256",
name: "weightedRate",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "multiWrapper",
outputs: [
{
internalType: "contract MultiWrapper",
name: "",
type: "address"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "oracles",
outputs: [
{
internalType: "contract IOracle[]",
name: "allOracles",
type: "address[]"
},
{
internalType: "enum OffchainOracle.OracleType[]",
name: "oracleTypes",
type: "uint8[]"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "owner",
outputs: [
{
internalType: "address",
name: "",
type: "address"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "contract IERC20",
name: "connector",
type: "address"
}
],
name: "removeConnector",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "contract IOracle",
name: "oracle",
type: "address"
},
{
internalType: "enum OffchainOracle.OracleType",
name: "oracleKind",
type: "uint8"
}
],
name: "removeOracle",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [],
name: "renounceOwnership",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "contract MultiWrapper",
name: "_multiWrapper",
type: "address"
}
],
name: "setMultiWrapper",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "address",
name: "newOwner",
type: "address"
}
],
name: "transferOwnership",
outputs: [],
stateMutability: "nonpayable",
type: "function"
}
];
class OffchainOracle__factory {
static createInterface() {
return new ethers.Interface(_abi$2);
}
static connect(address, runner) {
return new ethers.Contract(address, _abi$2, runner);
}
}
OffchainOracle__factory.abi = _abi$2;
const _abi$1 = [
{
inputs: [
{
internalType: "address",
name: "_owner",
type: "address"
}
],
stateMutability: "nonpayable",
type: "constructor"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "uint256",
name: "",
type: "uint256"
}
],
name: "DecimalsUpdated",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "uint256",
name: "",
type: "uint256"
}
],
name: "GasPriceUpdated",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "uint256",
name: "",
type: "uint256"
}
],
name: "L1BaseFeeUpdated",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "uint256",
name: "",
type: "uint256"
}
],
name: "OverheadUpdated",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "previousOwner",
type: "address"
},
{
indexed: true,
internalType: "address",
name: "newOwner",
type: "address"
}
],
name: "OwnershipTransferred",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "uint256",
name: "",
type: "uint256"
}
],
name: "ScalarUpdated",
type: "event"
},
{
inputs: [],
name: "decimals",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "gasPrice",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "bytes",
name: "_data",
type: "bytes"
}
],
name: "getL1Fee",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "bytes",
name: "_data",
type: "bytes"
}
],
name: "getL1GasUsed",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "l1BaseFee",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "overhead",
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: "renounceOwnership",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [],
name: "scalar",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "uint256",
name: "_decimals",
type: "uint256"
}
],
name: "setDecimals",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "uint256",
name: "_gasPrice",
type: "uint256"
}
],
name: "setGasPrice",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "uint256",
name: "_baseFee",
type: "uint256"
}
],
name: "setL1BaseFee",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "uint256",
name: "_overhead",
type: "uint256"
}
],
name: "setOverhead",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "uint256",
name: "_scalar",
type: "uint256"
}
],
name: "setScalar",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "address",
name: "newOwner",
type: "address"
}
],
name: "transferOwnership",
outputs: [],
stateMutability: "nonpayable",
type: "function"
}
];
class OvmGasPriceOracle__factory {
static createInterface() {
return new ethers.Interface(_abi$1);
}
static connect(address, runner) {
return new ethers.Contract(address, _abi$1, runner);
}
}
OvmGasPriceOracle__factory.abi = _abi$1;
const _abi = [
{
inputs: [
{
internalType: "contract ENS",
name: "_ens",
type: "address"
}
],
stateMutability: "nonpayable",
type: "constructor"
},
{
inputs: [
{
internalType: "address[]",
name: "addresses",
type: "address[]"
}
],
name: "getNames",
outputs: [
{
internalType: "string[]",
name: "r",
type: "string[]"
}
],
stateMutability: "view",
type: "function"
}
];
class ReverseRecords__factory {
static createInterface() {
return new ethers.Interface(_abi);
}
static connect(address, runner) {
return new ethers.Contract(address, _abi, runner);
}
}
ReverseRecords__factory.abi = _abi;
var index = /*#__PURE__*/Object.freeze({
__proto__: null,
ENS__factory: ENS__factory,
ERC20__factory: ERC20__factory,
Multicall__factory: Multicall__factory,
OffchainOracle__factory: OffchainOracle__factory,
OvmGasPriceOracle__factory: OvmGasPriceOracle__factory,
ReverseRecords__factory: ReverseRecords__factory
});
var __async$7 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
class Pedersen {
constructor() {
this.pedersenPromise = this.initPedersen();
}
initPedersen() {
return __async$7(this, null, function* () {
this.pedersenHash = yield circomlibjs.buildPedersenHash();
this.babyJub = this.pedersenHash.babyJub;
});
}
unpackPoint(buffer) {
return __async$7(this, null, function* () {
var _a, _b;
yield this.pedersenPromise;
return (_b = this.babyJub) == null ? void 0 : _b.unpackPoint((_a = this.pedersenHash) == null ? void 0 : _a.hash(buffer));
});
}
toStringBuffer(buffer) {
var _a;
return (_a = this.babyJub) == null ? void 0 : _a.F.toString(buffer);
}
}
const pedersen = new Pedersen();
function buffPedersenHash(buffer) {
return __async$7(this, null, function* () {
const [hash] = yield pedersen.unpackPoint(buffer);
return pedersen.toStringBuffer(hash);
});
}
var __async$6 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
function createDeposit(_0) {
return __async$6(this, arguments, function* ({ nullifier, secret }) {
const preimage = new Uint8Array([...leInt2Buff(nullifier), ...leInt2Buff(secret)]);
const noteHex = toFixedHex(bytesToBN(preimage), 62);
const commitment = BigInt(yield buffPedersenHash(preimage));
const commitmentHex = toFixedHex(commitment);
const nullifierHash = BigInt(yield buffPedersenHash(leInt2Buff(nullifier)));
const nullifierHex = toFixedHex(nullifierHash);
return {
preimage,
noteHex,
commitment,
commitmentHex,
nullifierHash,
nullifierHex
};
});
}
class Deposit {
constructor({
currency,
amount,
netId,
nullifier,
secret,
note,
noteHex,
invoice,
commitmentHex,
nullifierHex
}) {
this.currency = currency;
this.amount = amount;
this.netId = netId;
this.nullifier = nullifier;
this.secret = secret;
this.note = note;
this.noteHex = noteHex;
this.invoice = invoice;
this.commitmentHex = commitmentHex;
this.nullifierHex = nullifierHex;
}
toString() {
return JSON.stringify(
{
currency: this.currency,
amount: this.amount,
netId: this.netId,
nullifier: this.nullifier,
secret: this.secret,
note: this.note,
noteHex: this.noteHex,
invoice: this.invoice,
commitmentHex: this.commitmentHex,
nullifierHex: this.nullifierHex
},
null,
2
);
}
static createNote(_0) {
return __async$6(this, arguments, function* ({ currency, amount, netId, nullifier, secret }) {
if (!nullifier) {
nullifier = rBigInt(31);
}
if (!secret) {
secret = rBigInt(31);
}
const depositObject = yield createDeposit({
nullifier,
secret
});
const newDeposit = new Deposit({
currency: currency.toLowerCase(),
amount,
netId,
note: `tornado-${currency.toLowerCase()}-${amount}-${netId}-${depositObject.noteHex}`,
noteHex: depositObject.noteHex,
invoice: `tornadoInvoice-${currency.toLowerCase()}-${amount}-${netId}-${depositObject.commitmentHex}`,
nullifier,
secret,
commitmentHex: depositObject.commitmentHex,
nullifierHex: depositObject.nullifierHex
});
return newDeposit;
});
}
static parseNote(noteString) {
return __async$6(this, null, function* () {
const noteRegex = new RegExp("tornado-(?<currency>\\w+)-(?<amount>[\\d.]+)-(?<netId>\\d+)-0x(?<note>[0-9a-fA-F]{124})", "g");
const match = noteRegex.exec(noteString);
if (!match) {
throw new Error("The note has invalid format");
}
const matchGroup = match == null ? void 0 : match.groups;
const currency = matchGroup.currency.toLowerCase();
const amount = matchGroup.amount;
const netId = Number(matchGroup.netId);
const bytes = bnToBytes("0x" + matchGroup.note);
const nullifier = BigInt(leBuff2Int(bytes.slice(0, 31)).toString());
const secret = BigInt(leBuff2Int(bytes.slice(31, 62)).toString());
const depositObject = yield createDeposit({ nullifier, secret });
const invoice = `tornadoInvoice-${currency}-${amount}-${netId}-${depositObject.commitmentHex}`;
const newDeposit = new Deposit({
currency,
amount,
netId,
note: noteString,
noteHex: depositObject.noteHex,
invoice,
nullifier,
secret,
commitmentHex: depositObject.commitmentHex,
nullifierHex: depositObject.nullifierHex
});
return newDeposit;
});
}
}
class Invoice {
constructor(invoiceString) {
const invoiceRegex = new RegExp("tornadoInvoice-(?<currency>\\w+)-(?<amount>[\\d.]+)-(?<netId>\\d+)-0x(?<commitment>[0-9a-fA-F]{64})", "g");
const match = invoiceRegex.exec(invoiceString);
if (!match) {
throw new Error("The note has invalid format");
}
const matchGroup = match == null ? void 0 : match.groups;
const currency = matchGroup.currency.toLowerCase();
const amount = matchGroup.amount;
const netId = Number(matchGroup.netId);
this.currency = currency;
this.amount = amount;
this.netId = netId;
this.commitment = "0x" + matchGroup.commitment;
this.invoice = invoiceString;
}
toString() {
return JSON.stringify(
{
currency: this.currency,
amount: this.amount,
netId: this.netId,
commitment: this.commitment,
invoice: this.invoice
},
null,
2
);
}
}
function packEncryptedMessage({ nonce, ephemPublicKey, ciphertext }) {
const nonceBuf = toFixedHex(bytesToHex(base64ToBytes(nonce)), 24);
const ephemPublicKeyBuf = toFixedHex(bytesToHex(base64ToBytes(ephemPublicKey)), 32);
const ciphertextBuf = bytesToHex(base64ToBytes(ciphertext));
const messageBuff = concatBytes(hexToBytes(nonceBuf), hexToBytes(ephemPublicKeyBuf), hexToBytes(ciphertextBuf));
return bytesToHex(messageBuff);
}
function unpackEncryptedMessage(encryptedMessage) {
const messageBuff = hexToBytes(encryptedMessage);
const nonceBuf = bytesToBase64(messageBuff.slice(0, 24));
const ephemPublicKeyBuf = bytesToBase64(messageBuff.slice(24, 56));
const ciphertextBuf = bytesToBase64(messageBuff.slice(56));
return {
messageBuff: bytesToHex(messageBuff),
version: "x25519-xsalsa20-poly1305",
nonce: nonceBuf,
ephemPublicKey: ephemPublicKeyBuf,
ciphertext: ciphertextBuf
};
}
class NoteAccount {
constructor({ netId, blockNumber, recoveryKey, Echoer: Echoer2 }) {
if (!recoveryKey) {
recoveryKey = bytesToHex(crypto.getRandomValues(new Uint8Array(32))).slice(2);
}
this.netId = Math.floor(Number(netId));
this.blockNumber = blockNumber;
this.recoveryKey = recoveryKey;
this.recoveryAddress = ethers.computeAddress("0x" + recoveryKey);
this.recoveryPublicKey = ethSigUtil.getEncryptionPublicKey(recoveryKey);
this.Echoer = Echoer2;
}
/**
* Intends to mock eth_getEncryptionPublicKey behavior from MetaMask
* In order to make the recoveryKey retrival from Echoer possible from the bare private key
*/
static getWalletPublicKey(wallet) {
let { privateKey } = wallet;
if (privateKey.startsWith("0x")) {
privateKey = privateKey.replace("0x", "");
}
return ethSigUtil.getEncryptionPublicKey(privateKey);
}
// This function intends to provide an encrypted value of recoveryKey for an on-chain Echoer backup purpose
// Thus, the pubKey should be derived by a Wallet instance or from Web3 wallets
// pubKey: base64 encoded 32 bytes key from https://docs.metamask.io/wallet/reference/eth_getencryptionpublickey/
getEncryptedAccount(walletPublicKey) {
const encryptedData = ethSigUtil.encrypt({
publicKey: walletPublicKey,
data: this.recoveryKey,
version: "x25519-xsalsa20-poly1305"
});
const data = packEncryptedMessage(encryptedData);
return {
// Use this later to save hexPrivateKey generated with
// Buffer.from(JSON.stringify(encryptedData)).toString('hex')
// As we don't use buffer with this library we should leave UI to do the rest
encryptedData,
// Data that could be used as an echo(data) params
data
};
}
/**
* Decrypt Echoer backuped note encryption account with private keys
*/
decryptAccountsWithWallet(wallet, events) {
let { privateKey } = wallet;
if (privateKey.startsWith("0x")) {
privateKey = privateKey.replace("0x", "");
}
const decryptedEvents = [];
for (const event of events) {
try {
const unpackedMessage = unpackEncryptedMessage(event.encryptedAccount);
const recoveryKey = ethSigUtil.decrypt({
encryptedData: unpackedMessage,
privateKey
});
decryptedEvents.push(
new NoteAccount({
netId: this.netId,
blockNumber: event.blockNumber,
recoveryKey,
Echoer: this.Echoer
})
);
} catch (e) {
continue;
}
}
return decryptedEvents;
}
decryptNotes(events) {
const decryptedEvents = [];
for (const event of events) {
try {
const unpackedMessage = unpackEncryptedMessage(event.encryptedNote);
const [address, noteHex] = ethSigUtil.decrypt({
encryptedData: unpackedMessage,
privateKey: this.recoveryKey
}).split("-");
decryptedEvents.push({
blockNumber: event.blockNumber,
address: ethers.getAddress(address),
noteHex
});
} catch (e) {
continue;
}
}
return decryptedEvents;
}
encryptNote({ address, noteHex }) {
const encryptedData = ethSigUtil.encrypt({
publicKey: this.recoveryPublicKey,
data: `${address}-${noteHex}`,
version: "x25519-xsalsa20-poly1305"
});
return packEncryptedMessage(encryptedData);
}
}
const DUMMY_ADDRESS = "0x1111111111111111111111111111111111111111";
const DUMMY_NONCE = 1024;
const DUMMY_WITHDRAW_DATA = "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
function convertETHToTokenAmount(amountInWei, tokenPriceInWei, tokenDecimals = 18) {
const tokenDecimalsMultiplier = BigInt(10 ** Number(tokenDecimals));
return BigInt(amountInWei) * tokenDecimalsMultiplier / BigInt(tokenPriceInWei);
}
class TornadoFeeOracle {
constructor(ovmGasPriceOracle) {
if (ovmGasPriceOracle) {
this.ovmGasPriceOracle = ovmGasPriceOracle;
}
}
/**
* Calculate L1 fee for op-stack chains
*
* This is required since relayers would pay the full transaction fees for users
*/
fetchL1OptimismFee(tx) {
if (!this.ovmGasPriceOracle) {
return new Promise((resolve) => resolve(BigInt(0)));
}
if (!tx) {
tx = {
type: 0,
gasLimit: 1e6,
nonce: DUMMY_NONCE,
data: DUMMY_WITHDRAW_DATA,
gasPrice: ethers.parseUnits("1", "gwei"),
to: DUMMY_ADDRESS
};
}
return this.ovmGasPriceOracle.getL1Fee.staticCall(ethers.Transaction.from(tx).unsignedSerialized);
}
/**
* We don't need to distinguish default refunds by tokens since most users interact with other defi protocols after withdrawal
* So we default with 1M gas which is enough for two or three swaps
* Using 30 gwei for default but it is recommended to supply cached gasPrice value from the UI
*/
defaultEthRefund(gasPrice, gasLimit) {
return (gasPrice ? BigInt(gasPrice) : ethers.parseUnits("30", "gwei")) * BigInt(gasLimit || 1e6);
}
/**
* Calculates token amount for required ethRefund purchases required to calculate fees
*/
calculateTokenAmount(ethRefund, tokenPriceInEth, tokenDecimals) {
return convertETHToTokenAmount(ethRefund, tokenPriceInEth, tokenDecimals);
}
/**
* Warning: For tokens you need to check if the fees are above denomination
* (Usually happens for small denomination pool or if the gas price is high)
*/
calculateRelayerFee({
gasPrice,
gasLimit = 6e5,
l1Fee = 0,
denomination,
ethRefund = BigInt(0),
tokenPriceInWei,
tokenDecimals = 18,
relayerFeePercent = 0.33,
isEth = true,
premiumPercent = 20
}) {
const gasCosts = BigInt(gasPrice) * BigInt(gasLimit) + BigInt(l1Fee);
const relayerFee = BigInt(denomination) * BigInt(Math.floor(1e4 * relayerFeePercent)) / BigInt(1e4 * 100);
if (isEth) {
return (gasCosts + relayerFee) * BigInt(premiumPercent ? 100 + premiumPercent : 100) / BigInt(100);
}
const feeInEth = gasCosts + BigInt(ethRefund);
return (convertETHToTokenAmount(feeInEth, tokenPriceInWei, tokenDecimals) + relayerFee) * BigInt(premiumPercent ? 100 + premiumPercent : 100) / BigInt(100);
}
}
var __async$5 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
class Mimc {
constructor() {
this.mimcPromise = this.initMimc();
}
initMimc() {
return __async$5(this, null, function* () {
this.sponge = yield circomlibjs.buildMimcSponge();
this.hash = (left, right) => {
var _a, _b;
return (_b = this.sponge) == null ? void 0 : _b.F.toString((_a = this.sponge) == null ? void 0 : _a.multiHash([BigInt(left), BigInt(right)]));
};
});
}
getHash() {
return __async$5(this, null, function* () {
yield this.mimcPromise;
return {
sponge: this.sponge,
hash: this.hash
};
});
}
}
const mimc = new Mimc();
var __async$4 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
class MerkleTreeService {
constructor({
netId,
amount,
currency,
Tornado,
commitmentHex,
merkleTreeHeight = 20,
emptyElement = "21663839004416932945382355908790599225266501822907911457504978515578255421292",
merkleWorkerPath
}) {
const instanceName = `${netId}_${currency}_${amount}`;
this.currency = currency;
this.amount = amount;
this.netId = Number(netId);
this.Tornado = Tornado;
this.instanceName = instanceName;
this.commitmentHex = commitmentHex;
this.merkleTreeHeight = merkleTreeHeight;
this.emptyElement = emptyElement;
this.merkleWorkerPath = merkleWorkerPath;
}
createTree(events) {
return __async$4(this, null, function* () {
const { hash: hashFunction } = yield mimc.getHash();
if (this.merkleWorkerPath) {
console.log("Using merkleWorker\n");
try {
if (isNode) {
const merkleWorkerPromise = new Promise((resolve, reject) => {
const worker = new worker_threads.Worker(this.merkleWorkerPath, {
workerData: {
merkleTreeHeight: this.merkleTreeHeight,
elements: events,
zeroElement: this.emptyElement
}
});
worker.on("message", resolve);
worker.on("error", reject);
worker.on("exit", (code) => {
if (code !== 0) {
reject(new Error(`Worker stopped with exit code ${code}`));
}
});
});
return fixedMerkleTree.MerkleTree.deserialize(JSON.parse(yield merkleWorkerPromise), hashFunction);
} else {
const merkleWorkerPromise = new Promise((resolve, reject) => {
const worker = new Worker(this.merkleWorkerPath);
worker.onmessage = (e) => {
resolve(e.data);
};
worker.onerror = (e) => {
reject(e);
};
worker.postMessage({
merkleTreeHeight: this.merkleTreeHeight,
elements: events,
zeroElement: this.emptyElement
});
});
return fixedMerkleTree.MerkleTree.deserialize(JSON.parse(yield merkleWorkerPromise), hashFunction);
}
} catch (err) {
console.log("merkleWorker failed, falling back to synchronous merkle tree");
console.log(err);
}
}
return new fixedMerkleTree.MerkleTree(this.merkleTreeHeight, events, {
zeroElement: this.emptyElement,
hashFunction
});
});
}
createPartialTree(_0) {
return __async$4(this, arguments, function* ({ edge, elements }) {
const { hash: hashFunction } = yield mimc.getHash();
if (this.merkleWorkerPath) {
console.log("Using merkleWorker\n");
try {
if (isNode) {
const merkleWorkerPromise = new Promise((resolve, reject) => {
const worker = new worker_threads.Worker(this.merkleWorkerPath, {
workerData: {
merkleTreeHeight: this.merkleTreeHeight,
edge,
elements,
zeroElement: this.emptyElement
}
});
worker.on("message", resolve);
worker.on("error", reject);
worker.on("exit", (code) => {
if (code !== 0) {
reject(new Error(`Worker stopped with exit code ${code}`));
}
});
});
return fixedMerkleTree.PartialMerkleTree.deserialize(JSON.parse(yield merkleWorkerPromise), hashFunction);
} else {
const merkleWorkerPromise = new Promise((resolve, reject) => {
const worker = new Worker(this.merkleWorkerPath);
worker.onmessage = (e) => {
resolve(e.data);
};
worker.onerror = (e) => {
reject(e);
};
worker.postMessage({
merkleTreeHeight: this.merkleTreeHeight,
edge,
elements,
zeroElement: this.emptyElement
});
});
return fixedMerkleTree.PartialMerkleTree.deserialize(JSON.parse(yield merkleWorkerPromise), hashFunction);
}
} catch (err) {
console.log("merkleWorker failed, falling back to synchronous merkle tree");
console.log(err);
}
}
return new fixedMerkleTree.PartialMerkleTree(this.merkleTreeHeight, edge, elements, {
zeroElement: this.emptyElement,
hashFunction
});
});
}
verifyTree(events) {
return __async$4(this, null, function* () {
console.log(
`
Creating deposit tree for ${this.netId} ${this.amount} ${this.currency.toUpperCase()} would take a while
`
);
console.time("Created tree in");
const tree = yield this.createTree(events.map(({ commitment }) => commitment));
console.timeEnd("Created tree in");
console.log("");
const isKnownRoot = yield this.Tornado.isKnownRoot(toFixedHex(BigInt(tree.root)));
if (!isKnownRoot) {
const errMsg = `Deposit Event ${this.netId} ${this.amount} ${this.currency} is invalid`;
throw new Error(errMsg);
}
return tree;
});
}
}
var __async$3 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
function multicall(Multicall2, calls) {
return __async$3(this, null, function* () {
const calldata = calls.map((call) => {
var _a, _b, _c;
const target = ((_a = call.contract) == null ? void 0 : _a.target) || call.address;
const callInterface = ((_b = call.contract) == null ? void 0 : _b.interface) || call.interface;
return {
target,
callData: callInterface.encodeFunctionData(call.name, call.params),
allowFailure: (_c = call.allowFailure) != null ? _c : false
};
});
const returnData = yield Multicall2.aggregate3.staticCall(calldata);
const res = returnData.map((call, i) => {
var _a;
const callInterface = ((_a = calls[i].contract) == null ? void 0 : _a.interface) || calls[i].interface;
const [result, data] = call;
const decodeResult = result && data && data !== "0x" ? callInterface.decodeFunctionResult(calls[i].name, data) : null;
return !decodeResult ? null : decodeResult.length === 1 ? decodeResult[0] : decodeResult;
});
return res;
});
}
var __async$2 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
class TokenPriceOracle {
constructor(provider, multicall2, oracle) {
this.provider = provider;
this.multicall = multicall2;
this.oracle = oracle;
}
fetchPrices(tokens) {
return __async$2(this, null, function* () {
if (!this.oracle) {
return new Promise((resolve) => resolve(tokens.map(() => ethers.parseEther("0.0001"))));
}
const prices = yield multicall(
this.multicall,
tokens.map(({ tokenAddress }) => ({
contract: this.oracle,
name: "getRateToEth",
params: [tokenAddress, true]
}))
);
return prices.map((price, index) => {
return price * BigInt(10 ** tokens[index].decimals) / BigInt(10 ** 18);
});
});
}
}
var __async$1 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
function getTokenBalances(_0) {
return __async$1(this, arguments, function* ({
provider,
Multicall: Multicall2,
currencyName,
userAddress,
tokenAddresses = []
}) {
const tokenCalls = tokenAddresses.map((tokenAddress) => {
const Token = ERC20__factory.connect(tokenAddress, provider);
return [
{
contract: Token,
name: "balanceOf",
params: [userAddress]
},
{
contract: Token,
name: "name"
},
{
contract: Token,
name: "symbol"
},
{
contract: Token,
name: "decimals"
}
];
}).flat();
const multicallResults = yield multicall(Multicall2, [
{
contract: Multicall2,
name: "getEthBalance",
params: [userAddress]
},
...tokenCalls.length ? tokenCalls : []
]);
const ethResults = multicallResults[0];
const tokenResults = multicallResults.slice(1).length ? chunk(multicallResults.slice(1), tokenCalls.length / tokenAddresses.length) : [];
const tokenBalances = tokenResults.map((tokenResult, index) => {
const [tokenBalance, tokenName, tokenSymbol, tokenDecimals] = tokenResult;
const tokenAddress = tokenAddresses[index];
return {
address: tokenAddress,
name: tokenName,
symbol: tokenSymbol,
decimals: Number(tokenDecimals),
balance: tokenBalance
};
});
return [
{
address: ethers.ZeroAddress,
name: currencyName,
symbol: currencyName,
decimals: 18,
balance: ethResults
},
...tokenBalances
];
});
}
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
let groth16;
function initGroth16() {
return __async(this, null, function* () {
if (!groth16) {
groth16 = yield websnarkGroth({ wasmInitialMemory: 2e3 });
}
});
}
function calculateSnarkProof(input, circuit, provingKey) {
return __async(this, null, function* () {
if (!groth16) {
yield initGroth16();
}
const snarkInput = {
root: input.root,
nullifierHash: BigInt(input.nullifierHex).toString(),
recipient: BigInt(input.recipient),
relayer: BigInt(input.relayer),
fee: input.fee,
refund: input.refund,
nullifier: input.nullifier,
secret: input.secret,
pathElements: input.pathElements,
pathIndices: input.pathIndices
};
console.log("Start generating SNARK proof", snarkInput);
console.time("SNARK proof time");
const proofData = yield websnarkUtils__namespace.genWitnessAndProve(yield groth16, snarkInput, circuit, provingKey);
const proof = websnarkUtils__namespace.toSolidityInput(proofData).proof;
console.timeEnd("SNARK proof time");
const args = [
toFixedHex(input.root, 32),
toFixedHex(input.nullifierHex, 32),
input.recipient,
input.relayer,
toFixedHex(input.fee, 32),
toFixedHex(input.refund, 32)
];
return { proof, args };
});
}
exports.BaseEchoService = BaseEchoService;
exports.BaseEncryptedNotesService = BaseEncryptedNotesService;
exports.BaseEventsService = BaseEventsService;
exports.BaseGovernanceService = BaseGovernanceService;
exports.BaseRegistryService = BaseRegistryService;
exports.BaseTornadoService = BaseTornadoService;
exports.BatchBlockService = BatchBlockService;
exports.BatchEventsService = BatchEventsService;
exports.BatchTransactionService = BatchTransactionService;
exports.DEPOSIT = DEPOSIT;
exports.Deposit = Deposit;
exports.ENS__factory = ENS__factory;
exports.ERC20__factory = ERC20__factory;
exports.GET_DEPOSITS = GET_DEPOSITS;
exports.GET_ECHO_EVENTS = GET_ECHO_EVENTS;
exports.GET_ENCRYPTED_NOTES = GET_ENCRYPTED_NOTES;
exports.GET_GOVERNANCE_APY = GET_GOVERNANCE_APY;
exports.GET_GOVERNANCE_EVENTS = GET_GOVERNANCE_EVENTS;
exports.GET_NOTE_ACCOUNTS = GET_NOTE_ACCOUNTS;
exports.GET_REGISTERED = GET_REGISTERED;
exports.GET_STATISTIC = GET_STATISTIC;
exports.GET_WITHDRAWALS = GET_WITHDRAWALS;
exports.Invoice = Invoice;
exports.MAX_FEE = MAX_FEE;
exports.MIN_FEE = MIN_FEE;
exports.MIN_STAKE_BALANCE = MIN_STAKE_BALANCE;
exports.MerkleTreeService = MerkleTreeService;
exports.Mimc = Mimc;
exports.Multicall__factory = Multicall__factory;
exports.NetId = NetId;
exports.NoteAccount = NoteAccount;
exports.OffchainOracle__factory = OffchainOracle__factory;
exports.OvmGasPriceOracle__factory = OvmGasPriceOracle__factory;
exports.Pedersen = Pedersen;
exports.RelayerClient = RelayerClient;
exports.ReverseRecords__factory = ReverseRecords__factory;
exports.TokenPriceOracle = TokenPriceOracle;
exports.TornadoBrowserProvider = TornadoBrowserProvider;
exports.TornadoFeeOracle = TornadoFeeOracle;
exports.TornadoRpcSigner = TornadoRpcSigner;
exports.TornadoVoidSigner = TornadoVoidSigner;
exports.TornadoWallet = TornadoWallet;
exports.WITHDRAWAL = WITHDRAWAL;
exports._META = _META;
exports.addNetwork = addNetwork;
exports.ajv = ajv;
exports.base64ToBytes = base64ToBytes;
exports.bigIntReplacer = bigIntReplacer;
exports.bnToBytes = bnToBytes;
exports.buffPedersenHash = buffPedersenHash;
exports.bufferToBytes = bufferToBytes;
exports.bytesToBN = bytesToBN;
exports.bytesToBase64 = bytesToBase64;
exports.bytesToHex = bytesToHex;
exports.calculateScore = calculateScore;
exports.calculateSnarkProof = calculateSnarkProof;
exports.chunk = chunk;
exports.concatBytes = concatBytes;
exports.convertETHToTokenAmount = convertETHToTokenAmount;
exports.createDeposit = createDeposit;
exports.crypto = crypto;
exports.defaultConfig = defaultConfig;
exports.defaultUserAgent = defaultUserAgent;
exports.digest = digest;
exports.enabledChains = enabledChains;
exports.factories = index;
exports.fetch = fetch;
exports.fetchData = fetchData;
exports.fetchGetUrlFunc = fetchGetUrlFunc;
exports.getActiveTokenInstances = getActiveTokenInstances;
exports.getActiveTokens = getActiveTokens;
exports.getAllDeposits = getAllDeposits;
exports.getAllEncryptedNotes = getAllEncryptedNotes;
exports.getAllGovernanceEvents = getAllGovernanceEvents;
exports.getAllGraphEchoEvents = getAllGraphEchoEvents;
exports.getAllRegisters = getAllRegisters;
exports.getAllWithdrawals = getAllWithdrawals;
exports.getConfig = getConfig;
exports.getDeposits = getDeposits;
exports.getEncryptedNotes = getEncryptedNotes;
exports.getGovernanceEvents = getGovernanceEvents;
exports.getGraphEchoEvents = getGraphEchoEvents;
exports.getHttpAgent = getHttpAgent;
exports.getInstanceByAddress = getInstanceByAddress;
exports.getMeta = getMeta;
exports.getNetworkConfig = getNetworkConfig;
exports.getNoteAccounts = getNoteAccounts;
exports.getProvider = getProvider;
exports.getProviderWithNetId = getProviderWithNetId;
exports.getRegisters = getRegisters;
exports.getRelayerEnsSubdomains = getRelayerEnsSubdomains;
exports.getStatistic = getStatistic;
exports.getStatusSchema = getStatusSchema;
exports.getSupportedInstances = getSupportedInstances;
exports.getTokenBalances = getTokenBalances;
exports.getTovarishNetworks = getTovarishNetworks;
exports.getWeightRandom = getWeightRandom;
exports.getWithdrawals = getWithdrawals;
exports.hexToBytes = hexToBytes;
exports.initGroth16 = initGroth16;
exports.isNode = isNode;
exports.jobsSchema = jobsSchema;
exports.leBuff2Int = leBuff2Int;
exports.leInt2Buff = leInt2Buff;
exports.mimc = mimc;
exports.multicall = multicall;
exports.packEncryptedMessage = packEncryptedMessage;
exports.pedersen = pedersen;
exports.pickWeightedRandomRelayer = pickWeightedRandomRelayer;
exports.populateTransaction = populateTransaction;
exports.queryGraph = queryGraph;
exports.rBigInt = rBigInt;
exports.sleep = sleep;
exports.substring = substring;
exports.toFixedHex = toFixedHex;
exports.toFixedLength = toFixedLength;
exports.unpackEncryptedMessage = unpackEncryptedMessage;
exports.validateUrl = validateUrl;