Add BaseMultiTornadoService
This commit is contained in:
parent
b65998fca5
commit
a32659b8e4
38
dist/events/base.d.ts
vendored
38
dist/events/base.d.ts
vendored
@ -1,5 +1,6 @@
|
||||
import { BaseContract, Provider, EventLog } from 'ethers';
|
||||
import { Tornado, TornadoRouter, TornadoProxyLight, Governance, RelayerRegistry, Echoer, Aggregator } from '@tornado/contracts';
|
||||
import type { MerkleTree } from '@tornado/fixed-merkle-tree';
|
||||
import { BatchEventsService, BatchBlockService, BatchTransactionService, BatchEventOnProgress, BatchBlockOnProgress } from '../batch';
|
||||
import { fetchDataOptions } from '../providers';
|
||||
import { type NetIdType, type SubdomainMap } from '../networkConfig';
|
||||
@ -7,7 +8,8 @@ import { RelayerParams } from '../relayerClient';
|
||||
import type { TovarishClient } from '../tovarishClient';
|
||||
import type { ReverseRecords } from '../typechain';
|
||||
import type { MerkleTreeService } from '../merkleTree';
|
||||
import type { BaseEvents, CachedEvents, MinimalEvents, DepositsEvents, WithdrawalsEvents, EncryptedNotesEvents, AllGovernanceEvents, GovernanceProposalCreatedEvents, GovernanceVotedEvents, EchoEvents, AllRelayerRegistryEvents, StakeBurnedEvents } from './types';
|
||||
import type { DepositType } from '../deposits';
|
||||
import type { BaseEvents, CachedEvents, MinimalEvents, DepositsEvents, WithdrawalsEvents, EncryptedNotesEvents, AllGovernanceEvents, GovernanceProposalCreatedEvents, GovernanceVotedEvents, EchoEvents, AllRelayerRegistryEvents, StakeBurnedEvents, MultiDepositsEvents, MultiWithdrawalsEvents } from './types';
|
||||
export interface BaseEventsServiceConstructor {
|
||||
netId: NetIdType;
|
||||
provider: Provider;
|
||||
@ -56,7 +58,9 @@ export declare class BaseEventsService<EventType extends MinimalEvents> {
|
||||
/**
|
||||
* Handle saving events
|
||||
*/
|
||||
saveEvents({ events, lastBlock }: BaseEvents<EventType>): Promise<void>;
|
||||
saveEvents({ events, newEvents, lastBlock }: BaseEvents<EventType> & {
|
||||
newEvents: EventType[];
|
||||
}): Promise<void>;
|
||||
/**
|
||||
* Trigger saving and receiving latest events
|
||||
*/
|
||||
@ -90,6 +94,36 @@ export declare class BaseTornadoService extends BaseEventsService<DepositsEvents
|
||||
fromBlock: number;
|
||||
}): Promise<BaseEvents<DepositsEvents | WithdrawalsEvents>>;
|
||||
}
|
||||
export interface BaseMultiTornadoServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||
instances: {
|
||||
[key in string]: DepositType;
|
||||
};
|
||||
optionalTree?: boolean;
|
||||
merkleTreeService?: MerkleTreeService;
|
||||
}
|
||||
export declare class BaseMultiTornadoService extends BaseEventsService<MultiDepositsEvents | MultiWithdrawalsEvents> {
|
||||
instances: {
|
||||
[key in string]: DepositType;
|
||||
};
|
||||
optionalTree?: boolean;
|
||||
merkleTreeService?: MerkleTreeService;
|
||||
batchTransactionService: BatchTransactionService;
|
||||
batchBlockService: BatchBlockService;
|
||||
constructor(serviceConstructor: BaseMultiTornadoServiceConstructor);
|
||||
getInstanceName(): string;
|
||||
getTovarishType(): string;
|
||||
updateEventProgress({ percentage, type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
|
||||
formatEvents(events: EventLog[]): Promise<(MultiDepositsEvents | MultiWithdrawalsEvents)[]>;
|
||||
validateEvents<S>({ events, newEvents, }: BaseEvents<MultiDepositsEvents | MultiWithdrawalsEvents> & {
|
||||
newEvents: (MultiDepositsEvents | MultiWithdrawalsEvents)[];
|
||||
}): Promise<S>;
|
||||
getEvents(instanceAddress: string): Promise<{
|
||||
depositEvents: MultiDepositsEvents[];
|
||||
withdrawalEvents: MultiWithdrawalsEvents[];
|
||||
tree: MerkleTree | undefined;
|
||||
lastBlock: number;
|
||||
}>;
|
||||
}
|
||||
export interface BaseEchoServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||
Echoer: Echoer;
|
||||
}
|
||||
|
9
dist/events/types.d.ts
vendored
9
dist/events/types.d.ts
vendored
@ -83,6 +83,15 @@ export interface WithdrawalsEvents extends MinimalEvents {
|
||||
fee: string;
|
||||
timestamp: number;
|
||||
}
|
||||
export interface BaseMultiTornadoEvents {
|
||||
event: string;
|
||||
instanceAddress: string;
|
||||
}
|
||||
export interface MultiDepositsEvents extends BaseMultiTornadoEvents, DepositsEvents {
|
||||
}
|
||||
export interface MultiWithdrawalsEvents extends BaseMultiTornadoEvents, WithdrawalsEvents {
|
||||
relayerAddress: string;
|
||||
}
|
||||
export interface EchoEvents extends MinimalEvents {
|
||||
address: string;
|
||||
encryptedAccount: string;
|
||||
|
174
dist/index.js
vendored
174
dist/index.js
vendored
@ -1426,7 +1426,7 @@ function getActiveTokenInstances(config) {
|
||||
}
|
||||
function getInstanceByAddress(config, address) {
|
||||
const { tokens, disabledTokens } = config;
|
||||
for (const [currency, { instanceAddress }] of Object.entries(tokens)) {
|
||||
for (const [currency, { instanceAddress, tokenAddress, symbol, decimals }] of Object.entries(tokens)) {
|
||||
if (disabledTokens?.includes(currency)) {
|
||||
continue;
|
||||
}
|
||||
@ -1434,7 +1434,10 @@ function getInstanceByAddress(config, address) {
|
||||
if (instance === address) {
|
||||
return {
|
||||
amount,
|
||||
currency
|
||||
currency,
|
||||
symbol,
|
||||
decimals,
|
||||
tokenAddress
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1447,6 +1450,21 @@ function getRelayerEnsSubdomains() {
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
function getMultiInstances(netId, config) {
|
||||
return Object.entries(config.tokens).reduce(
|
||||
(acc, [currency, { instanceAddress }]) => {
|
||||
Object.entries(instanceAddress).forEach(([amount, contractAddress]) => {
|
||||
acc[contractAddress] = {
|
||||
currency,
|
||||
amount,
|
||||
netId
|
||||
};
|
||||
});
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
const ajv = new Ajv({ allErrors: true });
|
||||
ajv.addKeyword({
|
||||
@ -2226,7 +2244,7 @@ class BaseEventsService {
|
||||
* Handle saving events
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async saveEvents({ events, lastBlock }) {
|
||||
async saveEvents({ events, newEvents, lastBlock }) {
|
||||
}
|
||||
/**
|
||||
* Trigger saving and receiving latest events
|
||||
@ -2257,7 +2275,7 @@ class BaseEventsService {
|
||||
lastBlock
|
||||
});
|
||||
if (savedEvents.fromCache || newEvents.events.length) {
|
||||
await this.saveEvents({ events: allEvents, lastBlock });
|
||||
await this.saveEvents({ events: allEvents, newEvents: newEvents.events, lastBlock });
|
||||
}
|
||||
return {
|
||||
events: allEvents,
|
||||
@ -2368,6 +2386,152 @@ class BaseTornadoService extends BaseEventsService {
|
||||
});
|
||||
}
|
||||
}
|
||||
class BaseMultiTornadoService extends BaseEventsService {
|
||||
instances;
|
||||
optionalTree;
|
||||
merkleTreeService;
|
||||
batchTransactionService;
|
||||
batchBlockService;
|
||||
constructor(serviceConstructor) {
|
||||
const { instances, provider, optionalTree, merkleTreeService } = serviceConstructor;
|
||||
const contract = merkleTreeService?.Tornado || contracts.Tornado__factory.connect(Object.keys(instances)[0], provider);
|
||||
super({
|
||||
...serviceConstructor,
|
||||
contract,
|
||||
type: "*"
|
||||
});
|
||||
this.batchEventsService = new BatchEventsService({
|
||||
provider,
|
||||
contract,
|
||||
address: Object.keys(instances),
|
||||
onProgress: this.updateEventProgress
|
||||
});
|
||||
this.instances = instances;
|
||||
this.optionalTree = optionalTree;
|
||||
this.merkleTreeService = merkleTreeService;
|
||||
this.batchTransactionService = new BatchTransactionService({
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress
|
||||
});
|
||||
this.batchBlockService = new BatchBlockService({
|
||||
provider,
|
||||
onProgress: this.updateBlockProgress
|
||||
});
|
||||
}
|
||||
getInstanceName() {
|
||||
return `tornado_${this.netId}`;
|
||||
}
|
||||
getTovarishType() {
|
||||
return "tornado";
|
||||
}
|
||||
updateEventProgress({ percentage, type, fromBlock, toBlock, count }) {
|
||||
console.log({ percentage, type, fromBlock, toBlock, count });
|
||||
}
|
||||
async formatEvents(events) {
|
||||
const txs = await this.batchTransactionService.getBatchTransactions([
|
||||
...new Set(
|
||||
events.filter(({ eventName }) => eventName === "Deposit").map(({ transactionHash }) => transactionHash)
|
||||
)
|
||||
]);
|
||||
const blocks = await this.batchBlockService.getBatchBlocks([
|
||||
...new Set(
|
||||
events.filter(({ eventName }) => eventName === "Withdrawal").map(({ blockNumber }) => blockNumber)
|
||||
)
|
||||
]);
|
||||
return events.map(
|
||||
({
|
||||
address: instanceAddress,
|
||||
blockNumber,
|
||||
index: logIndex,
|
||||
transactionHash,
|
||||
args,
|
||||
eventName: event
|
||||
}) => {
|
||||
const eventObjects = {
|
||||
blockNumber,
|
||||
logIndex,
|
||||
transactionHash,
|
||||
event,
|
||||
instanceAddress
|
||||
};
|
||||
if (event === "Deposit") {
|
||||
const { commitment, leafIndex, timestamp } = args;
|
||||
return {
|
||||
...eventObjects,
|
||||
commitment,
|
||||
leafIndex: Number(leafIndex),
|
||||
timestamp: Number(timestamp),
|
||||
from: txs.find(({ hash }) => hash === transactionHash)?.from || ""
|
||||
};
|
||||
}
|
||||
if (event === "Withdrawal") {
|
||||
const { nullifierHash, to, relayer: relayerAddress, fee } = args;
|
||||
return {
|
||||
...eventObjects,
|
||||
logIndex,
|
||||
transactionHash,
|
||||
nullifierHash: String(nullifierHash),
|
||||
to,
|
||||
relayerAddress,
|
||||
fee: String(fee),
|
||||
timestamp: blocks.find(({ number }) => number === blockNumber)?.timestamp || 0
|
||||
};
|
||||
}
|
||||
}
|
||||
).filter((e) => e);
|
||||
}
|
||||
async validateEvents({
|
||||
events,
|
||||
newEvents
|
||||
}) {
|
||||
const instancesWithNewEvents = [
|
||||
...new Set(
|
||||
newEvents.filter(({ event }) => event === "Deposit").map(({ instanceAddress }) => instanceAddress)
|
||||
)
|
||||
];
|
||||
let tree;
|
||||
const requiredTree = this.merkleTreeService?.Tornado?.target;
|
||||
if (requiredTree && !instancesWithNewEvents.includes(requiredTree)) {
|
||||
instancesWithNewEvents.push(requiredTree);
|
||||
}
|
||||
for (const instance of instancesWithNewEvents) {
|
||||
const depositEvents = events.filter(
|
||||
({ instanceAddress, event }) => instanceAddress === instance && event === "Deposit"
|
||||
);
|
||||
const lastEvent = depositEvents[depositEvents.length - 1];
|
||||
if (lastEvent.leafIndex !== depositEvents.length - 1) {
|
||||
const errMsg = `Invalid deposit events for ${instance} wants ${depositEvents.length - 1} leafIndex have ${lastEvent.leafIndex}`;
|
||||
throw new Error(errMsg);
|
||||
}
|
||||
if (requiredTree === instance && !this.optionalTree) {
|
||||
tree = await this.merkleTreeService?.verifyTree(depositEvents);
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
async getEvents(instanceAddress) {
|
||||
const { events, validateResult: tree, lastBlock } = await this.updateEvents();
|
||||
const { depositEvents, withdrawalEvents } = events.reduce(
|
||||
(acc, curr) => {
|
||||
if (curr.instanceAddress === instanceAddress) {
|
||||
if (curr.event === "Deposit") {
|
||||
acc.depositEvents.push(curr);
|
||||
} else if (curr.event === "Withdrawal") {
|
||||
acc.withdrawalEvents.push(curr);
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
return {
|
||||
depositEvents,
|
||||
withdrawalEvents,
|
||||
tree,
|
||||
lastBlock
|
||||
};
|
||||
}
|
||||
}
|
||||
class BaseEchoService extends BaseEventsService {
|
||||
constructor(serviceConstructor) {
|
||||
super({
|
||||
@ -10411,6 +10575,7 @@ exports.BaseEchoService = BaseEchoService;
|
||||
exports.BaseEncryptedNotesService = BaseEncryptedNotesService;
|
||||
exports.BaseEventsService = BaseEventsService;
|
||||
exports.BaseGovernanceService = BaseGovernanceService;
|
||||
exports.BaseMultiTornadoService = BaseMultiTornadoService;
|
||||
exports.BaseRegistryService = BaseRegistryService;
|
||||
exports.BaseRevenueService = BaseRevenueService;
|
||||
exports.BaseTornadoService = BaseTornadoService;
|
||||
@ -10502,6 +10667,7 @@ exports.getEventsSchemaValidator = getEventsSchemaValidator;
|
||||
exports.getHttpAgent = getHttpAgent;
|
||||
exports.getIndexedDB = getIndexedDB;
|
||||
exports.getInstanceByAddress = getInstanceByAddress;
|
||||
exports.getMultiInstances = getMultiInstances;
|
||||
exports.getNetworkConfig = getNetworkConfig;
|
||||
exports.getPermit2CommitmentsSignature = getPermit2CommitmentsSignature;
|
||||
exports.getPermit2Signature = getPermit2Signature;
|
||||
|
174
dist/index.mjs
vendored
174
dist/index.mjs
vendored
@ -1404,7 +1404,7 @@ function getActiveTokenInstances(config) {
|
||||
}
|
||||
function getInstanceByAddress(config, address) {
|
||||
const { tokens, disabledTokens } = config;
|
||||
for (const [currency, { instanceAddress }] of Object.entries(tokens)) {
|
||||
for (const [currency, { instanceAddress, tokenAddress, symbol, decimals }] of Object.entries(tokens)) {
|
||||
if (disabledTokens?.includes(currency)) {
|
||||
continue;
|
||||
}
|
||||
@ -1412,7 +1412,10 @@ function getInstanceByAddress(config, address) {
|
||||
if (instance === address) {
|
||||
return {
|
||||
amount,
|
||||
currency
|
||||
currency,
|
||||
symbol,
|
||||
decimals,
|
||||
tokenAddress
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1425,6 +1428,21 @@ function getRelayerEnsSubdomains() {
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
function getMultiInstances(netId, config) {
|
||||
return Object.entries(config.tokens).reduce(
|
||||
(acc, [currency, { instanceAddress }]) => {
|
||||
Object.entries(instanceAddress).forEach(([amount, contractAddress]) => {
|
||||
acc[contractAddress] = {
|
||||
currency,
|
||||
amount,
|
||||
netId
|
||||
};
|
||||
});
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
const ajv = new Ajv({ allErrors: true });
|
||||
ajv.addKeyword({
|
||||
@ -2204,7 +2222,7 @@ class BaseEventsService {
|
||||
* Handle saving events
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async saveEvents({ events, lastBlock }) {
|
||||
async saveEvents({ events, newEvents, lastBlock }) {
|
||||
}
|
||||
/**
|
||||
* Trigger saving and receiving latest events
|
||||
@ -2235,7 +2253,7 @@ class BaseEventsService {
|
||||
lastBlock
|
||||
});
|
||||
if (savedEvents.fromCache || newEvents.events.length) {
|
||||
await this.saveEvents({ events: allEvents, lastBlock });
|
||||
await this.saveEvents({ events: allEvents, newEvents: newEvents.events, lastBlock });
|
||||
}
|
||||
return {
|
||||
events: allEvents,
|
||||
@ -2346,6 +2364,152 @@ class BaseTornadoService extends BaseEventsService {
|
||||
});
|
||||
}
|
||||
}
|
||||
class BaseMultiTornadoService extends BaseEventsService {
|
||||
instances;
|
||||
optionalTree;
|
||||
merkleTreeService;
|
||||
batchTransactionService;
|
||||
batchBlockService;
|
||||
constructor(serviceConstructor) {
|
||||
const { instances, provider, optionalTree, merkleTreeService } = serviceConstructor;
|
||||
const contract = merkleTreeService?.Tornado || Tornado__factory.connect(Object.keys(instances)[0], provider);
|
||||
super({
|
||||
...serviceConstructor,
|
||||
contract,
|
||||
type: "*"
|
||||
});
|
||||
this.batchEventsService = new BatchEventsService({
|
||||
provider,
|
||||
contract,
|
||||
address: Object.keys(instances),
|
||||
onProgress: this.updateEventProgress
|
||||
});
|
||||
this.instances = instances;
|
||||
this.optionalTree = optionalTree;
|
||||
this.merkleTreeService = merkleTreeService;
|
||||
this.batchTransactionService = new BatchTransactionService({
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress
|
||||
});
|
||||
this.batchBlockService = new BatchBlockService({
|
||||
provider,
|
||||
onProgress: this.updateBlockProgress
|
||||
});
|
||||
}
|
||||
getInstanceName() {
|
||||
return `tornado_${this.netId}`;
|
||||
}
|
||||
getTovarishType() {
|
||||
return "tornado";
|
||||
}
|
||||
updateEventProgress({ percentage, type, fromBlock, toBlock, count }) {
|
||||
console.log({ percentage, type, fromBlock, toBlock, count });
|
||||
}
|
||||
async formatEvents(events) {
|
||||
const txs = await this.batchTransactionService.getBatchTransactions([
|
||||
...new Set(
|
||||
events.filter(({ eventName }) => eventName === "Deposit").map(({ transactionHash }) => transactionHash)
|
||||
)
|
||||
]);
|
||||
const blocks = await this.batchBlockService.getBatchBlocks([
|
||||
...new Set(
|
||||
events.filter(({ eventName }) => eventName === "Withdrawal").map(({ blockNumber }) => blockNumber)
|
||||
)
|
||||
]);
|
||||
return events.map(
|
||||
({
|
||||
address: instanceAddress,
|
||||
blockNumber,
|
||||
index: logIndex,
|
||||
transactionHash,
|
||||
args,
|
||||
eventName: event
|
||||
}) => {
|
||||
const eventObjects = {
|
||||
blockNumber,
|
||||
logIndex,
|
||||
transactionHash,
|
||||
event,
|
||||
instanceAddress
|
||||
};
|
||||
if (event === "Deposit") {
|
||||
const { commitment, leafIndex, timestamp } = args;
|
||||
return {
|
||||
...eventObjects,
|
||||
commitment,
|
||||
leafIndex: Number(leafIndex),
|
||||
timestamp: Number(timestamp),
|
||||
from: txs.find(({ hash }) => hash === transactionHash)?.from || ""
|
||||
};
|
||||
}
|
||||
if (event === "Withdrawal") {
|
||||
const { nullifierHash, to, relayer: relayerAddress, fee } = args;
|
||||
return {
|
||||
...eventObjects,
|
||||
logIndex,
|
||||
transactionHash,
|
||||
nullifierHash: String(nullifierHash),
|
||||
to,
|
||||
relayerAddress,
|
||||
fee: String(fee),
|
||||
timestamp: blocks.find(({ number }) => number === blockNumber)?.timestamp || 0
|
||||
};
|
||||
}
|
||||
}
|
||||
).filter((e) => e);
|
||||
}
|
||||
async validateEvents({
|
||||
events,
|
||||
newEvents
|
||||
}) {
|
||||
const instancesWithNewEvents = [
|
||||
...new Set(
|
||||
newEvents.filter(({ event }) => event === "Deposit").map(({ instanceAddress }) => instanceAddress)
|
||||
)
|
||||
];
|
||||
let tree;
|
||||
const requiredTree = this.merkleTreeService?.Tornado?.target;
|
||||
if (requiredTree && !instancesWithNewEvents.includes(requiredTree)) {
|
||||
instancesWithNewEvents.push(requiredTree);
|
||||
}
|
||||
for (const instance of instancesWithNewEvents) {
|
||||
const depositEvents = events.filter(
|
||||
({ instanceAddress, event }) => instanceAddress === instance && event === "Deposit"
|
||||
);
|
||||
const lastEvent = depositEvents[depositEvents.length - 1];
|
||||
if (lastEvent.leafIndex !== depositEvents.length - 1) {
|
||||
const errMsg = `Invalid deposit events for ${instance} wants ${depositEvents.length - 1} leafIndex have ${lastEvent.leafIndex}`;
|
||||
throw new Error(errMsg);
|
||||
}
|
||||
if (requiredTree === instance && !this.optionalTree) {
|
||||
tree = await this.merkleTreeService?.verifyTree(depositEvents);
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
async getEvents(instanceAddress) {
|
||||
const { events, validateResult: tree, lastBlock } = await this.updateEvents();
|
||||
const { depositEvents, withdrawalEvents } = events.reduce(
|
||||
(acc, curr) => {
|
||||
if (curr.instanceAddress === instanceAddress) {
|
||||
if (curr.event === "Deposit") {
|
||||
acc.depositEvents.push(curr);
|
||||
} else if (curr.event === "Withdrawal") {
|
||||
acc.withdrawalEvents.push(curr);
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
return {
|
||||
depositEvents,
|
||||
withdrawalEvents,
|
||||
tree,
|
||||
lastBlock
|
||||
};
|
||||
}
|
||||
}
|
||||
class BaseEchoService extends BaseEventsService {
|
||||
constructor(serviceConstructor) {
|
||||
super({
|
||||
@ -10385,4 +10549,4 @@ async function calculateSnarkProof(input, circuit, provingKey) {
|
||||
return { proof, args };
|
||||
}
|
||||
|
||||
export { BaseEchoService, BaseEncryptedNotesService, BaseEventsService, BaseGovernanceService, BaseRegistryService, BaseRevenueService, BaseTornadoService, BatchBlockService, BatchEventsService, BatchTransactionService, DBEchoService, DBEncryptedNotesService, DBGovernanceService, DBRegistryService, DBRevenueService, DBTornadoService, Deposit, ENSNameWrapper__factory, ENSRegistry__factory, ENSResolver__factory, ENSUtils, ENS__factory, ERC20__factory, EnsContracts, INDEX_DB_ERROR, IndexedDB, Invoice, MAX_FEE, MAX_TOVARISH_EVENTS, MIN_FEE, MIN_STAKE_BALANCE, MerkleTreeService, Mimc, Multicall__factory, NetId, NoteAccount, OffchainOracle__factory, OvmGasPriceOracle__factory, Pedersen, RelayerClient, ReverseRecords__factory, TokenPriceOracle, TornadoBrowserProvider, TornadoFeeOracle, TornadoRpcSigner, TornadoVoidSigner, TornadoWallet, TovarishClient, addNetwork, addressSchemaType, ajv, base64ToBytes, bigIntReplacer, bnSchemaType, bnToBytes, buffPedersenHash, bufferToBytes, bytes32BNSchemaType, bytes32SchemaType, bytesToBN, bytesToBase64, bytesToHex, calculateScore, calculateSnarkProof, chunk, concatBytes, convertETHToTokenAmount, createDeposit, crypto, customConfig, defaultConfig, defaultUserAgent, deployHasher, depositsEventsSchema, digest, downloadZip, echoEventsSchema, enabledChains, encodedLabelToLabelhash, encryptedNotesSchema, index as factories, fetchData, fetchGetUrlFunc, fetchIp, fromContentHash, gasZipID, gasZipInbounds, gasZipInput, gasZipMinMax, getActiveTokenInstances, getActiveTokens, getConfig, getEventsSchemaValidator, getHttpAgent, getIndexedDB, getInstanceByAddress, getNetworkConfig, getPermit2CommitmentsSignature, getPermit2Signature, getPermitCommitmentsSignature, getPermitSignature, getProvider, getProviderWithNetId, getRelayerEnsSubdomains, getStatusSchema, getSubInfo, getSupportedInstances, getTokenBalances, getTovarishNetworks, getWeightRandom, governanceEventsSchema, hasherBytecode, hexToBytes, initGroth16, isHex, isNode, jobRequestSchema, jobsSchema, labelhash, leBuff2Int, leInt2Buff, loadDBEvents, loadRemoteEvents, makeLabelNodeAndParent, mimc, multiQueryFilter, multicall, numberFormatter, packEncryptedMessage, parseInvoice, parseNote, pedersen, permit2Address, pickWeightedRandomRelayer, populateTransaction, proofSchemaType, proposalState, rBigInt, rHex, relayerRegistryEventsSchema, saveDBEvents, sleep, stakeBurnedEventsSchema, substring, toContentHash, toFixedHex, toFixedLength, unpackEncryptedMessage, unzipAsync, validateUrl, withdrawalsEventsSchema, zipAsync };
|
||||
export { BaseEchoService, BaseEncryptedNotesService, BaseEventsService, BaseGovernanceService, BaseMultiTornadoService, BaseRegistryService, BaseRevenueService, BaseTornadoService, BatchBlockService, BatchEventsService, BatchTransactionService, DBEchoService, DBEncryptedNotesService, DBGovernanceService, DBRegistryService, DBRevenueService, DBTornadoService, Deposit, ENSNameWrapper__factory, ENSRegistry__factory, ENSResolver__factory, ENSUtils, ENS__factory, ERC20__factory, EnsContracts, INDEX_DB_ERROR, IndexedDB, Invoice, MAX_FEE, MAX_TOVARISH_EVENTS, MIN_FEE, MIN_STAKE_BALANCE, MerkleTreeService, Mimc, Multicall__factory, NetId, NoteAccount, OffchainOracle__factory, OvmGasPriceOracle__factory, Pedersen, RelayerClient, ReverseRecords__factory, TokenPriceOracle, TornadoBrowserProvider, TornadoFeeOracle, TornadoRpcSigner, TornadoVoidSigner, TornadoWallet, TovarishClient, addNetwork, addressSchemaType, ajv, base64ToBytes, bigIntReplacer, bnSchemaType, bnToBytes, buffPedersenHash, bufferToBytes, bytes32BNSchemaType, bytes32SchemaType, bytesToBN, bytesToBase64, bytesToHex, calculateScore, calculateSnarkProof, chunk, concatBytes, convertETHToTokenAmount, createDeposit, crypto, customConfig, defaultConfig, defaultUserAgent, deployHasher, depositsEventsSchema, digest, downloadZip, echoEventsSchema, enabledChains, encodedLabelToLabelhash, encryptedNotesSchema, index as factories, fetchData, fetchGetUrlFunc, fetchIp, fromContentHash, gasZipID, gasZipInbounds, gasZipInput, gasZipMinMax, getActiveTokenInstances, getActiveTokens, getConfig, getEventsSchemaValidator, getHttpAgent, getIndexedDB, getInstanceByAddress, getMultiInstances, getNetworkConfig, getPermit2CommitmentsSignature, getPermit2Signature, getPermitCommitmentsSignature, getPermitSignature, getProvider, getProviderWithNetId, getRelayerEnsSubdomains, getStatusSchema, getSubInfo, getSupportedInstances, getTokenBalances, getTovarishNetworks, getWeightRandom, governanceEventsSchema, hasherBytecode, hexToBytes, initGroth16, isHex, isNode, jobRequestSchema, jobsSchema, labelhash, leBuff2Int, leInt2Buff, loadDBEvents, loadRemoteEvents, makeLabelNodeAndParent, mimc, multiQueryFilter, multicall, numberFormatter, packEncryptedMessage, parseInvoice, parseNote, pedersen, permit2Address, pickWeightedRandomRelayer, populateTransaction, proofSchemaType, proposalState, rBigInt, rHex, relayerRegistryEventsSchema, saveDBEvents, sleep, stakeBurnedEventsSchema, substring, toContentHash, toFixedHex, toFixedLength, unpackEncryptedMessage, unzipAsync, validateUrl, withdrawalsEventsSchema, zipAsync };
|
||||
|
7
dist/networkConfig.d.ts
vendored
7
dist/networkConfig.d.ts
vendored
@ -1,3 +1,4 @@
|
||||
import type { DepositType } from './deposits';
|
||||
/**
|
||||
* Type of default supported networks
|
||||
*/
|
||||
@ -114,5 +115,11 @@ export declare function getActiveTokenInstances(config: Config): TokenInstances;
|
||||
export declare function getInstanceByAddress(config: Config, address: string): {
|
||||
amount: string;
|
||||
currency: string;
|
||||
symbol: string;
|
||||
decimals: number;
|
||||
tokenAddress: string | undefined;
|
||||
} | undefined;
|
||||
export declare function getRelayerEnsSubdomains(): SubdomainMap;
|
||||
export declare function getMultiInstances(netId: NetIdType, config: Config): {
|
||||
[key in string]: DepositType;
|
||||
};
|
||||
|
176
dist/tornado.umd.js
vendored
176
dist/tornado.umd.js
vendored
@ -60854,6 +60854,7 @@ __webpack_require__.d(__webpack_exports__, {
|
||||
O_: () => (/* binding */ BaseEncryptedNotesService),
|
||||
uw: () => (/* binding */ BaseEventsService),
|
||||
JJ: () => (/* binding */ BaseGovernanceService),
|
||||
lG: () => (/* binding */ BaseMultiTornadoService),
|
||||
cE: () => (/* binding */ BaseRegistryService),
|
||||
Do: () => (/* binding */ BaseRevenueService),
|
||||
e0: () => (/* binding */ BaseTornadoService),
|
||||
@ -90513,7 +90514,7 @@ class BaseEventsService {
|
||||
* Handle saving events
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async saveEvents({ events, lastBlock }) {
|
||||
async saveEvents({ events, newEvents, lastBlock }) {
|
||||
}
|
||||
/**
|
||||
* Trigger saving and receiving latest events
|
||||
@ -90544,7 +90545,7 @@ class BaseEventsService {
|
||||
lastBlock
|
||||
});
|
||||
if (savedEvents.fromCache || newEvents.events.length) {
|
||||
await this.saveEvents({ events: allEvents, lastBlock });
|
||||
await this.saveEvents({ events: allEvents, newEvents: newEvents.events, lastBlock });
|
||||
}
|
||||
return {
|
||||
events: allEvents,
|
||||
@ -90655,6 +90656,152 @@ class BaseTornadoService extends BaseEventsService {
|
||||
});
|
||||
}
|
||||
}
|
||||
class BaseMultiTornadoService extends BaseEventsService {
|
||||
instances;
|
||||
optionalTree;
|
||||
merkleTreeService;
|
||||
batchTransactionService;
|
||||
batchBlockService;
|
||||
constructor(serviceConstructor) {
|
||||
const { instances, provider, optionalTree, merkleTreeService } = serviceConstructor;
|
||||
const contract = merkleTreeService?.Tornado || Tornado__factory.connect(Object.keys(instances)[0], provider);
|
||||
super({
|
||||
...serviceConstructor,
|
||||
contract,
|
||||
type: "*"
|
||||
});
|
||||
this.batchEventsService = new batch/* BatchEventsService */.JY({
|
||||
provider,
|
||||
contract,
|
||||
address: Object.keys(instances),
|
||||
onProgress: this.updateEventProgress
|
||||
});
|
||||
this.instances = instances;
|
||||
this.optionalTree = optionalTree;
|
||||
this.merkleTreeService = merkleTreeService;
|
||||
this.batchTransactionService = new batch/* BatchTransactionService */.AF({
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress
|
||||
});
|
||||
this.batchBlockService = new batch/* BatchBlockService */.B3({
|
||||
provider,
|
||||
onProgress: this.updateBlockProgress
|
||||
});
|
||||
}
|
||||
getInstanceName() {
|
||||
return `tornado_${this.netId}`;
|
||||
}
|
||||
getTovarishType() {
|
||||
return "tornado";
|
||||
}
|
||||
updateEventProgress({ percentage, type, fromBlock, toBlock, count }) {
|
||||
console.log({ percentage, type, fromBlock, toBlock, count });
|
||||
}
|
||||
async formatEvents(events) {
|
||||
const txs = await this.batchTransactionService.getBatchTransactions([
|
||||
...new Set(
|
||||
events.filter(({ eventName }) => eventName === "Deposit").map(({ transactionHash }) => transactionHash)
|
||||
)
|
||||
]);
|
||||
const blocks = await this.batchBlockService.getBatchBlocks([
|
||||
...new Set(
|
||||
events.filter(({ eventName }) => eventName === "Withdrawal").map(({ blockNumber }) => blockNumber)
|
||||
)
|
||||
]);
|
||||
return events.map(
|
||||
({
|
||||
address: instanceAddress,
|
||||
blockNumber,
|
||||
index: logIndex,
|
||||
transactionHash,
|
||||
args,
|
||||
eventName: event
|
||||
}) => {
|
||||
const eventObjects = {
|
||||
blockNumber,
|
||||
logIndex,
|
||||
transactionHash,
|
||||
event,
|
||||
instanceAddress
|
||||
};
|
||||
if (event === "Deposit") {
|
||||
const { commitment, leafIndex, timestamp } = args;
|
||||
return {
|
||||
...eventObjects,
|
||||
commitment,
|
||||
leafIndex: Number(leafIndex),
|
||||
timestamp: Number(timestamp),
|
||||
from: txs.find(({ hash }) => hash === transactionHash)?.from || ""
|
||||
};
|
||||
}
|
||||
if (event === "Withdrawal") {
|
||||
const { nullifierHash, to, relayer: relayerAddress, fee } = args;
|
||||
return {
|
||||
...eventObjects,
|
||||
logIndex,
|
||||
transactionHash,
|
||||
nullifierHash: String(nullifierHash),
|
||||
to,
|
||||
relayerAddress,
|
||||
fee: String(fee),
|
||||
timestamp: blocks.find(({ number }) => number === blockNumber)?.timestamp || 0
|
||||
};
|
||||
}
|
||||
}
|
||||
).filter((e) => e);
|
||||
}
|
||||
async validateEvents({
|
||||
events,
|
||||
newEvents
|
||||
}) {
|
||||
const instancesWithNewEvents = [
|
||||
...new Set(
|
||||
newEvents.filter(({ event }) => event === "Deposit").map(({ instanceAddress }) => instanceAddress)
|
||||
)
|
||||
];
|
||||
let tree;
|
||||
const requiredTree = this.merkleTreeService?.Tornado?.target;
|
||||
if (requiredTree && !instancesWithNewEvents.includes(requiredTree)) {
|
||||
instancesWithNewEvents.push(requiredTree);
|
||||
}
|
||||
for (const instance of instancesWithNewEvents) {
|
||||
const depositEvents = events.filter(
|
||||
({ instanceAddress, event }) => instanceAddress === instance && event === "Deposit"
|
||||
);
|
||||
const lastEvent = depositEvents[depositEvents.length - 1];
|
||||
if (lastEvent.leafIndex !== depositEvents.length - 1) {
|
||||
const errMsg = `Invalid deposit events for ${instance} wants ${depositEvents.length - 1} leafIndex have ${lastEvent.leafIndex}`;
|
||||
throw new Error(errMsg);
|
||||
}
|
||||
if (requiredTree === instance && !this.optionalTree) {
|
||||
tree = await this.merkleTreeService?.verifyTree(depositEvents);
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
async getEvents(instanceAddress) {
|
||||
const { events, validateResult: tree, lastBlock } = await this.updateEvents();
|
||||
const { depositEvents, withdrawalEvents } = events.reduce(
|
||||
(acc, curr) => {
|
||||
if (curr.instanceAddress === instanceAddress) {
|
||||
if (curr.event === "Deposit") {
|
||||
acc.depositEvents.push(curr);
|
||||
} else if (curr.event === "Withdrawal") {
|
||||
acc.withdrawalEvents.push(curr);
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
return {
|
||||
depositEvents,
|
||||
withdrawalEvents,
|
||||
tree,
|
||||
lastBlock
|
||||
};
|
||||
}
|
||||
}
|
||||
class BaseEchoService extends BaseEventsService {
|
||||
constructor(serviceConstructor) {
|
||||
super({
|
||||
@ -91662,6 +91809,7 @@ __webpack_require__.r(__webpack_exports__);
|
||||
/* harmony export */ BaseEncryptedNotesService: () => (/* reexport safe */ _base__WEBPACK_IMPORTED_MODULE_1__.O_),
|
||||
/* harmony export */ BaseEventsService: () => (/* reexport safe */ _base__WEBPACK_IMPORTED_MODULE_1__.uw),
|
||||
/* harmony export */ BaseGovernanceService: () => (/* reexport safe */ _base__WEBPACK_IMPORTED_MODULE_1__.JJ),
|
||||
/* harmony export */ BaseMultiTornadoService: () => (/* reexport safe */ _base__WEBPACK_IMPORTED_MODULE_1__.lG),
|
||||
/* harmony export */ BaseRegistryService: () => (/* reexport safe */ _base__WEBPACK_IMPORTED_MODULE_1__.cE),
|
||||
/* harmony export */ BaseRevenueService: () => (/* reexport safe */ _base__WEBPACK_IMPORTED_MODULE_1__.Do),
|
||||
/* harmony export */ BaseTornadoService: () => (/* reexport safe */ _base__WEBPACK_IMPORTED_MODULE_1__.e0),
|
||||
@ -92866,6 +93014,7 @@ async function multicall(Multicall2, calls) {
|
||||
/* harmony export */ h9: () => (/* binding */ getActiveTokens),
|
||||
/* harmony export */ o2: () => (/* binding */ getRelayerEnsSubdomains),
|
||||
/* harmony export */ oY: () => (/* binding */ getActiveTokenInstances),
|
||||
/* harmony export */ sX: () => (/* binding */ getMultiInstances),
|
||||
/* harmony export */ sb: () => (/* binding */ defaultConfig),
|
||||
/* harmony export */ zj: () => (/* binding */ getConfig),
|
||||
/* harmony export */ zr: () => (/* binding */ NetId)
|
||||
@ -93468,7 +93617,7 @@ function getActiveTokenInstances(config) {
|
||||
}
|
||||
function getInstanceByAddress(config, address) {
|
||||
const { tokens, disabledTokens } = config;
|
||||
for (const [currency, { instanceAddress }] of Object.entries(tokens)) {
|
||||
for (const [currency, { instanceAddress, tokenAddress, symbol, decimals }] of Object.entries(tokens)) {
|
||||
if (disabledTokens?.includes(currency)) {
|
||||
continue;
|
||||
}
|
||||
@ -93476,7 +93625,10 @@ function getInstanceByAddress(config, address) {
|
||||
if (instance === address) {
|
||||
return {
|
||||
amount,
|
||||
currency
|
||||
currency,
|
||||
symbol,
|
||||
decimals,
|
||||
tokenAddress
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -93489,6 +93641,21 @@ function getRelayerEnsSubdomains() {
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
function getMultiInstances(netId, config) {
|
||||
return Object.entries(config.tokens).reduce(
|
||||
(acc, [currency, { instanceAddress }]) => {
|
||||
Object.entries(instanceAddress).forEach(([amount, contractAddress]) => {
|
||||
acc[contractAddress] = {
|
||||
currency,
|
||||
amount,
|
||||
netId
|
||||
};
|
||||
});
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
@ -217571,6 +217738,7 @@ __webpack_require__.r(__webpack_exports__);
|
||||
/* harmony export */ getHttpAgent: () => (/* reexport safe */ _providers__WEBPACK_IMPORTED_MODULE_19__.WU),
|
||||
/* harmony export */ getIndexedDB: () => (/* reexport safe */ _idb__WEBPACK_IMPORTED_MODULE_10__.W7),
|
||||
/* harmony export */ getInstanceByAddress: () => (/* reexport safe */ _networkConfig__WEBPACK_IMPORTED_MODULE_15__.Zh),
|
||||
/* harmony export */ getMultiInstances: () => (/* reexport safe */ _networkConfig__WEBPACK_IMPORTED_MODULE_15__.sX),
|
||||
/* harmony export */ getNetworkConfig: () => (/* reexport safe */ _networkConfig__WEBPACK_IMPORTED_MODULE_15__.RY),
|
||||
/* harmony export */ getPermit2CommitmentsSignature: () => (/* reexport safe */ _permit__WEBPACK_IMPORTED_MODULE_17__.Sl),
|
||||
/* harmony export */ getPermit2Signature: () => (/* reexport safe */ _permit__WEBPACK_IMPORTED_MODULE_17__.KM),
|
||||
|
2
dist/tornado.umd.min.js
vendored
2
dist/tornado.umd.min.js
vendored
File diff suppressed because one or more lines are too long
@ -22,6 +22,7 @@ import {
|
||||
Tornado__factory,
|
||||
} from '@tornado/contracts';
|
||||
|
||||
import type { MerkleTree } from '@tornado/fixed-merkle-tree';
|
||||
import {
|
||||
BatchEventsService,
|
||||
BatchBlockService,
|
||||
@ -37,6 +38,7 @@ import type { TovarishClient } from '../tovarishClient';
|
||||
|
||||
import type { ReverseRecords } from '../typechain';
|
||||
import type { MerkleTreeService } from '../merkleTree';
|
||||
import type { DepositType } from '../deposits';
|
||||
import type {
|
||||
BaseEvents,
|
||||
CachedEvents,
|
||||
@ -56,6 +58,8 @@ import type {
|
||||
WorkerUnregisteredEvents,
|
||||
AllRelayerRegistryEvents,
|
||||
StakeBurnedEvents,
|
||||
MultiDepositsEvents,
|
||||
MultiWithdrawalsEvents,
|
||||
} from './types';
|
||||
|
||||
export interface BaseEventsServiceConstructor {
|
||||
@ -237,7 +241,7 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async saveEvents({ events, lastBlock }: BaseEvents<EventType>) {}
|
||||
async saveEvents({ events, newEvents, lastBlock }: BaseEvents<EventType> & { newEvents: EventType[] }) {}
|
||||
|
||||
/**
|
||||
* Trigger saving and receiving latest events
|
||||
@ -280,7 +284,7 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
||||
|
||||
// If the events are loaded from cache or we have found new events, save them
|
||||
if ((savedEvents as CachedEvents<EventType>).fromCache || newEvents.events.length) {
|
||||
await this.saveEvents({ events: allEvents, lastBlock });
|
||||
await this.saveEvents({ events: allEvents, newEvents: newEvents.events, lastBlock });
|
||||
}
|
||||
|
||||
return {
|
||||
@ -429,6 +433,203 @@ export class BaseTornadoService extends BaseEventsService<DepositsEvents | Withd
|
||||
}
|
||||
}
|
||||
|
||||
export interface BaseMultiTornadoServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||
instances: {
|
||||
[key in string]: DepositType;
|
||||
};
|
||||
optionalTree?: boolean;
|
||||
merkleTreeService?: MerkleTreeService;
|
||||
}
|
||||
|
||||
export class BaseMultiTornadoService extends BaseEventsService<MultiDepositsEvents | MultiWithdrawalsEvents> {
|
||||
instances: {
|
||||
[key in string]: DepositType;
|
||||
};
|
||||
|
||||
optionalTree?: boolean;
|
||||
merkleTreeService?: MerkleTreeService;
|
||||
batchTransactionService: BatchTransactionService;
|
||||
batchBlockService: BatchBlockService;
|
||||
|
||||
constructor(serviceConstructor: BaseMultiTornadoServiceConstructor) {
|
||||
const { instances, provider, optionalTree, merkleTreeService } = serviceConstructor;
|
||||
|
||||
const contract =
|
||||
merkleTreeService?.Tornado || Tornado__factory.connect(Object.keys(instances)[0] as string, provider);
|
||||
|
||||
super({
|
||||
...serviceConstructor,
|
||||
contract,
|
||||
type: '*',
|
||||
});
|
||||
|
||||
this.batchEventsService = new BatchEventsService({
|
||||
provider,
|
||||
contract,
|
||||
address: Object.keys(instances),
|
||||
onProgress: this.updateEventProgress,
|
||||
});
|
||||
|
||||
this.instances = instances;
|
||||
|
||||
this.optionalTree = optionalTree;
|
||||
this.merkleTreeService = merkleTreeService;
|
||||
|
||||
this.batchTransactionService = new BatchTransactionService({
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress,
|
||||
});
|
||||
|
||||
this.batchBlockService = new BatchBlockService({
|
||||
provider,
|
||||
onProgress: this.updateBlockProgress,
|
||||
});
|
||||
}
|
||||
|
||||
getInstanceName(): string {
|
||||
return `tornado_${this.netId}`;
|
||||
}
|
||||
|
||||
getTovarishType(): string {
|
||||
return 'tornado';
|
||||
}
|
||||
|
||||
updateEventProgress({ percentage, type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]) {
|
||||
console.log({ percentage, type, fromBlock, toBlock, count });
|
||||
}
|
||||
|
||||
async formatEvents(events: EventLog[]): Promise<(MultiDepositsEvents | MultiWithdrawalsEvents)[]> {
|
||||
const txs = await this.batchTransactionService.getBatchTransactions([
|
||||
...new Set(
|
||||
events.filter(({ eventName }) => eventName === 'Deposit').map(({ transactionHash }) => transactionHash),
|
||||
),
|
||||
]);
|
||||
|
||||
const blocks = await this.batchBlockService.getBatchBlocks([
|
||||
...new Set(
|
||||
events.filter(({ eventName }) => eventName === 'Withdrawal').map(({ blockNumber }) => blockNumber),
|
||||
),
|
||||
]);
|
||||
|
||||
return events
|
||||
.map(
|
||||
({
|
||||
address: instanceAddress,
|
||||
blockNumber,
|
||||
index: logIndex,
|
||||
transactionHash,
|
||||
args,
|
||||
eventName: event,
|
||||
}) => {
|
||||
const eventObjects = {
|
||||
blockNumber,
|
||||
logIndex,
|
||||
transactionHash,
|
||||
event,
|
||||
instanceAddress,
|
||||
};
|
||||
|
||||
if (event === 'Deposit') {
|
||||
const { commitment, leafIndex, timestamp } = args;
|
||||
|
||||
return {
|
||||
...eventObjects,
|
||||
commitment: commitment as string,
|
||||
leafIndex: Number(leafIndex),
|
||||
timestamp: Number(timestamp),
|
||||
from: txs.find(({ hash }) => hash === transactionHash)?.from || '',
|
||||
} as MultiDepositsEvents;
|
||||
}
|
||||
|
||||
if (event === 'Withdrawal') {
|
||||
const { nullifierHash, to, relayer: relayerAddress, fee } = args;
|
||||
|
||||
return {
|
||||
...eventObjects,
|
||||
logIndex,
|
||||
transactionHash,
|
||||
nullifierHash: String(nullifierHash),
|
||||
to,
|
||||
relayerAddress,
|
||||
fee: String(fee),
|
||||
timestamp: blocks.find(({ number }) => number === blockNumber)?.timestamp || 0,
|
||||
} as MultiWithdrawalsEvents;
|
||||
}
|
||||
},
|
||||
)
|
||||
.filter((e) => e) as (MultiDepositsEvents | MultiWithdrawalsEvents)[];
|
||||
}
|
||||
|
||||
async validateEvents<S>({
|
||||
events,
|
||||
newEvents,
|
||||
}: BaseEvents<MultiDepositsEvents | MultiWithdrawalsEvents> & {
|
||||
newEvents: (MultiDepositsEvents | MultiWithdrawalsEvents)[];
|
||||
}) {
|
||||
const instancesWithNewEvents = [
|
||||
...new Set(
|
||||
newEvents.filter(({ event }) => event === 'Deposit').map(({ instanceAddress }) => instanceAddress),
|
||||
),
|
||||
];
|
||||
|
||||
let tree: S | undefined;
|
||||
|
||||
const requiredTree = this.merkleTreeService?.Tornado?.target as string | undefined;
|
||||
|
||||
// Audit and create deposit tree
|
||||
if (requiredTree && !instancesWithNewEvents.includes(requiredTree)) {
|
||||
instancesWithNewEvents.push(requiredTree);
|
||||
}
|
||||
|
||||
for (const instance of instancesWithNewEvents) {
|
||||
const depositEvents = events.filter(
|
||||
({ instanceAddress, event }) => instanceAddress === instance && event === 'Deposit',
|
||||
) as MultiDepositsEvents[];
|
||||
|
||||
const lastEvent = depositEvents[depositEvents.length - 1];
|
||||
|
||||
if (lastEvent.leafIndex !== depositEvents.length - 1) {
|
||||
const errMsg = `Invalid deposit events for ${instance} wants ${depositEvents.length - 1} leafIndex have ${lastEvent.leafIndex}`;
|
||||
throw new Error(errMsg);
|
||||
}
|
||||
|
||||
if (requiredTree === instance && !this.optionalTree) {
|
||||
tree = (await this.merkleTreeService?.verifyTree(depositEvents)) as S;
|
||||
}
|
||||
}
|
||||
|
||||
return tree as S;
|
||||
}
|
||||
|
||||
async getEvents(instanceAddress: string) {
|
||||
const { events, validateResult: tree, lastBlock } = await this.updateEvents<MerkleTree | undefined>();
|
||||
|
||||
const { depositEvents, withdrawalEvents } = events.reduce(
|
||||
(acc, curr) => {
|
||||
if (curr.instanceAddress === instanceAddress) {
|
||||
if (curr.event === 'Deposit') {
|
||||
acc.depositEvents.push(curr as MultiDepositsEvents);
|
||||
} else if (curr.event === 'Withdrawal') {
|
||||
acc.withdrawalEvents.push(curr as MultiWithdrawalsEvents);
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{} as {
|
||||
depositEvents: MultiDepositsEvents[];
|
||||
withdrawalEvents: MultiWithdrawalsEvents[];
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
depositEvents,
|
||||
withdrawalEvents,
|
||||
tree,
|
||||
lastBlock,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface BaseEchoServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||
Echoer: Echoer;
|
||||
}
|
||||
|
@ -113,6 +113,17 @@ export interface WithdrawalsEvents extends MinimalEvents {
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface BaseMultiTornadoEvents {
|
||||
event: string;
|
||||
instanceAddress: string;
|
||||
}
|
||||
|
||||
export interface MultiDepositsEvents extends BaseMultiTornadoEvents, DepositsEvents {}
|
||||
|
||||
export interface MultiWithdrawalsEvents extends BaseMultiTornadoEvents, WithdrawalsEvents {
|
||||
relayerAddress: string;
|
||||
}
|
||||
|
||||
export interface EchoEvents extends MinimalEvents {
|
||||
address: string;
|
||||
encryptedAccount: string;
|
||||
|
@ -1,3 +1,5 @@
|
||||
import type { DepositType } from './deposits';
|
||||
|
||||
/**
|
||||
* Type of default supported networks
|
||||
*/
|
||||
@ -725,7 +727,7 @@ export function getActiveTokenInstances(config: Config): TokenInstances {
|
||||
export function getInstanceByAddress(config: Config, address: string) {
|
||||
const { tokens, disabledTokens } = config;
|
||||
|
||||
for (const [currency, { instanceAddress }] of Object.entries(tokens)) {
|
||||
for (const [currency, { instanceAddress, tokenAddress, symbol, decimals }] of Object.entries(tokens)) {
|
||||
if (disabledTokens?.includes(currency)) {
|
||||
continue;
|
||||
}
|
||||
@ -734,6 +736,9 @@ export function getInstanceByAddress(config: Config, address: string) {
|
||||
return {
|
||||
amount,
|
||||
currency,
|
||||
symbol,
|
||||
decimals,
|
||||
tokenAddress,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -748,3 +753,19 @@ export function getRelayerEnsSubdomains() {
|
||||
return acc;
|
||||
}, {} as SubdomainMap);
|
||||
}
|
||||
|
||||
export function getMultiInstances(netId: NetIdType, config: Config): { [key in string]: DepositType } {
|
||||
return Object.entries(config.tokens).reduce(
|
||||
(acc, [currency, { instanceAddress }]) => {
|
||||
Object.entries(instanceAddress).forEach(([amount, contractAddress]) => {
|
||||
acc[contractAddress] = {
|
||||
currency,
|
||||
amount,
|
||||
netId,
|
||||
};
|
||||
});
|
||||
return acc;
|
||||
},
|
||||
{} as { [key in string]: DepositType },
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user