/// <reference types="node" />
import { EventEmitter } from 'events';
import { DB, TransactionDB } from 'anondb';
import { ethers } from 'ethers';
import { IncrementalMerkleTree } from '@unirep/utils';
/**
 * The type of data to be processed in an event handler.
 */
type EventHandlerArgs = {
    event: ethers.Event;
    decodedData: {
        [key: string]: any;
    };
    db: TransactionDB;
};
/**
 * Turn either a decimal or hex string to a decimal string.
 * @param content A `bigint`, `string` or `number` type data.
 * @returns A decimal string.
 */
export declare function toDecString(content: bigint | string | number): string;
/**
 * The synchronizer is used to construct the Unirep state. After events are emitted from the Unirep contract,
 * the synchronizer will verify the events and then save the states.
 * @example
 * ```ts
 * import { Synchronizer } from '@unirep/core'
 *
 * const state = new Synchronizer({
 *   unirepAddress: '0xaabbccaabbccaabbccaabbccaabbccaabbccaaaa',
 *   provider, // an ethers.js provider
 * })
 *
 * // start the synchronizer deamon
 * await state.start()
 * await state.waitForSync()
 *
 * // stop the synchronizer deamon
 * state.stop()
 * ```
 */
export declare class Synchronizer extends EventEmitter {
    /**
     * @private
     * The database object.
     */
    private _db;
    /**
     * @private
     * The provider which is connected in the synchronizer.
     */
    private _provider;
    /**
     * @private
     * The UniRep smart contract object which is connected in the synchronizer.
     */
    private _unirepContract;
    /**
     * @private
     * The array of attester IDs which are synchronized in the synchronizer.
     */
    private _attesterId;
    /**
     * @private
     * The circuits settings.
     */
    private _settings;
    /**
     * @private
     * The settings of attesters. There are `startTimestamp` and `epochLength` of each attester.
     */
    private _attesterSettings;
    /**
     * @protected
     * The default zero [state tree](https://developer.unirep.io/docs/protocol/trees#state-tree) leaf.
     */
    protected defaultStateTreeLeaf: bigint;
    /**
     * @protected
     * The default zero [epoch tree](https://developer.unirep.io/docs/protocol/trees#epoch-tree) leaf.
     */
    protected defaultEpochTreeLeaf: bigint;
    /**
     * @private
     * Indicates if the synchronizer is to sync with all Unirep attesters.
     */
    private _syncAll;
    /**
     * @private
     * The mapping of the event name and its handler
     */
    private _eventHandlers;
    /**
     * @private
     * The mapping of a contract address and its event filters.
     */
    private _eventFilters;
    /**
     * @private
     * The id of the poll event.
     */
    private pollId;
    /**
     * How frequently the synchronizer will poll the blockchain for new events (specified in milliseconds). Default: `5000`
     */
    pollRate: number;
    /**
     * How many blocks the synchronizer will query on each poll. Default: `100000`
     */
    blockRate: number;
    /**
     * Allow passing the genesis block as the starting block for querying events
     */
    private _genesisBlock;
    /**
     * @private
     * Check if a setup is completed or not.
     */
    private setupComplete;
    /**
     * @private
     * If a setup is not completed, there will be a setup promise.
     */
    private setupPromise;
    /**
     * @private
     * Lock on poll event.
     */
    private lock;
    /**
     * @private
     * Load events promises.
     */
    private promises;
    /**
     * @private
     * Unprocessed events.
     */
    private _blocks;
    /**
     * @private
     * The latest completed block number.
     */
    private _blockEnd;
    constructor(config: {
        db?: DB;
        attesterId?: bigint | bigint[];
        provider: ethers.providers.Provider;
        unirepAddress: string;
        genesisBlock?: number;
    });
    private buildEventHandlers;
    /**
     * Read the database object.
     */
    get db(): DB;
    /**
     * Read the provider which is connected in the synchronizer.
     */
    get provider(): ethers.providers.Provider;
    /**
     * Read the UniRep smart contract object which is connected in the synchronizer.
     */
    get unirepContract(): ethers.Contract;
    /**
     * Read the settings of the UniRep smart contract.
     */
    get settings(): any;
    /**
     * Read the genesis block of the provider environment.
     */
    get genesisBlock(): number;
    /**
     * The default attester ID that is set when constructed.
     * If there is a list of attester IDs, then the first one will be the default attester ID.
     * If no attester ID is given during construction, all attesters will be synchronized and the default `attesterId` will be `BigInt(0)`.
     *
     * :::caution
     * The default attester ID should be checked carefully while synchronizing more than one attester.
     * The default attester ID can be changed with [setAttesterId](#setattesterid).
     * :::
     */
    get attesterId(): bigint;
    get attestersOrClauses(): any[];
    /**
     * Change default [attesterId](#attesterid) to another attester ID.
     * It will fail if an `attesterId` is not synchronized during construction.
     * @param attesterId The default attester Id to be set.
     */
    setAttesterId(attesterId: string | bigint): void;
    /**
     * Check if attester events are synchronized in this synchronizer.
     * @param attesterId The queried attester ID.
     * @returns True if the attester events are synced, false otherwise.
     */
    attesterExist(attesterId: string | bigint): boolean;
    /**
     * Check if attester events are synchronized in this synchronizer. It will throw an error if the attester is not synchronized.
     * @param attesterId The queried attester ID.
     */
    checkAttesterId(attesterId: string | bigint): void;
    /**
     * Run setup promises.
     * @returns Setup promises.
     */
    setup(): Promise<any>;
    /**
     * Query settings from smart contract and setup event handlers.
     */
    _setup(): Promise<void>;
    /**
     * Find the attester's genesis block in the Unirep smart contract.
     * Then store the `startTimestamp` and `epochLength` in database and in the memory.
     */
    private _findStartBlock;
    /**
     * Start the synchronizer daemon.
     * Start polling the blockchain for new events. If we're behind the HEAD block we'll poll many times quickly
     */
    start(): Promise<void>;
    /**
     * Stop synchronizing with Unirep contract.
     */
    stop(): void;
    /**
     * Manually poll for new events.
     * Returns a boolean indicating whether the synchronizer has synced to the head of the blockchain.
     */
    poll(): Promise<{
        complete: boolean;
    }>;
    /**
     * @private
     * Execute polling events and processing events.
     */
    private _poll;
    /**
     * Load more events from the smart contract.
     * @param n How many blocks will be loaded.
     */
    loadBlocks(n: number): Promise<void>;
    /**
     * Load new event from smart contract.
     * @param fromBlock From which block number.
     * @param toBlock To which block number.
     * @returns All events in the block range.
     */
    loadNewEvents(fromBlock: number, toBlock: number): Promise<any[]>;
    /**
     * Overwrite this to query events in different attester addresses.
     * @example
     * ```ts
     * export class AppSynchronizer extends Synchronizer {
     * ...
     *   get contracts(){
     *     return {
     *       ...super.contracts,
     *       [this.appContract.address]: {
     *           contract: this.appContract,
     *           eventNames: [
     *             'Event1',
     *             'Event2',
     *             'Event3',
     *             ...
     *           ]
     *       }
     *   }
     * }
     * ```
     */
    get contracts(): {
        [x: string]: {
            contract: ethers.Contract;
            eventNames: string[];
        };
    };
    /**
     * Process events with each event handler.
     * @param events The array of events will be proccessed.
     */
    private processEvents;
    /**
     * Wait for the synchronizer to sync up to a certain block.
     * By default this will wait until the current latest known block (according to the provider).
     * @param blockNumber The block number to be synced to.
     */
    waitForSync(blockNumber?: number): Promise<void>;
    /**
     * Get the latest processed epoch from the database.
     *
     * :::caution
     * This value may mismatch the onchain value depending on synchronization status.
     * :::
     * @param attesterId The queried attester Id.
     * @returns `{number: number, sealed: boolean}`
     */
    readCurrentEpoch(attesterId?: bigint | string): Promise<any>;
    /**
     * Calculate the current epoch determining the amount of time since the attester registration timestamp.
     * This operation is **synchronous** and does not involve any database operations.
     * @param attesterId The queried attester Id.
     * @returns The number of current calculated epoch.
     */
    calcCurrentEpoch(attesterId?: bigint | string): number;
    /**
     * Calculate the amount of time remaining in the current epoch. This operation is **synchronous** and does not involve any database operations.
     * @param attesterId The queried attester Id.
     * @returns Current calculated time to the next epoch.
     */
    calcEpochRemainingTime(attesterId?: bigint | string): number;
    /**
     * Load the current epoch number from the blockchain.
     *
     * :::tip
     * Use this function in test environments where the blockchain timestamp may not match the real timestamp (e.g. due to snapshot/revert patterns).
     * :::
     * @param attesterId The queried attester Id.
     * @returns The number of current epoch on-chain.
     */
    loadCurrentEpoch(attesterId?: bigint | string): Promise<number>;
    /**
     * Get the epoch tree root for a certain epoch.
     * @param epoch The epoch to be queried.
     * @param attesterId The attester to be queried.
     * @returns The epoch tree root.
     */
    epochTreeRoot(epoch: number, attesterId?: bigint | string): Promise<any>;
    /**
     * Build a merkle inclusion proof for the tree from a certain epoch.
     * @param epoch The epoch to be queried.
     * @param leafIndex The leaf index to be queried.
     * @param attesterId The attester to be queried.
     * @returns The merkle proof of the epoch tree index.
     */
    epochTreeProof(epoch: number, leafIndex: any, attesterId?: bigint | string): Promise<import("@zk-kit/incremental-merkle-tree").MerkleProof>;
    /**
     * Determine if a [nullifier](https://developer.unirep.io/docs/protocol/nullifiers) exists. All nullifiers are stored in a single mapping and expected to be globally unique.
     * @param nullifier A nullifier to be queried.
     * @returns True if the nullifier exists on-chain before, false otherwise.
     */
    nullifierExist(nullifier: any): Promise<any>;
    /**
     * Build the latest state tree for a certain epoch.
     * @param epoch The epoch to be queried.
     * @param attesterId The attester to be queried.
     * @returns The state tree.
     */
    genStateTree(epoch: number | bigint, attesterId?: bigint | string): Promise<IncrementalMerkleTree>;
    /**
     * Build the latest history tree for the current attester.
     * @param attesterId The attester to be queried.
     * @returns The history tree.
     */
    genHistoryTree(attesterId?: bigint | string): Promise<IncrementalMerkleTree>;
    /**
     * Build the latest epoch tree for a certain epoch.
     * @param epoch The epoch to be queried.
     * @param attesterId The attester to be queried.
     * @returns The epoch tree.
     */
    genEpochTree(epoch: number | bigint, attesterId?: bigint | string): Promise<IncrementalMerkleTree>;
    /**
     * Determine if a state root exists in a certain epoch.
     * @param root The queried global state tree root
     * @param epoch The queried epoch of the global state tree
     * @param attesterId The attester to be queried.
     * @returns True if the global state tree root exists, false otherwise.
     */
    stateTreeRootExists(root: bigint | string, epoch: number, attesterId?: bigint | string): Promise<any>;
    /**
     * Check if the epoch tree root is stored in the database.
     * @note
     * :::caution
     * Epoch tree root of current epoch might change frequently and the tree root is not stored everytime.
     * Try use this function when querying the epoch tree in the **previous epoch**.
     * :::
     * @param root The queried epoch tree root
     * @param epoch The queried epoch of the epoch tree
     * @param attesterId The attester to be queried.
     * @returns True if the epoch tree root is in the database, false otherwise.
     */
    epochTreeRootExists(root: bigint | string, epoch: number, attesterId?: bigint | string): Promise<boolean>;
    /**
     * Get the number of state tree leaves in a certain epoch.
     * @param epoch The queried epoch.
     * @returns The number of the state tree leaves.
     */
    numStateTreeLeaves(epoch: number, attesterId?: bigint | string): Promise<number>;
    /**
     * Handle state tree leaf event
     * @param args `EventHandlerArgs` type arguments.
     * @returns True if succeeds, false otherwise.
     */
    handleStateTreeLeaf({ event, db, decodedData }: EventHandlerArgs): Promise<true | undefined>;
    /**
     * Handle epoch tree leaf event
     * @param args `EventHandlerArgs` type arguments.
     * @returns True if succeeds, false otherwise.
     */
    handleEpochTreeLeaf({ event, db, decodedData }: EventHandlerArgs): Promise<true | undefined>;
    /**
     * Handle user signup event
     * @param args `EventHandlerArgs` type arguments.
     * @returns True if succeeds, false otherwise.
     */
    handleUserSignedUp({ decodedData, event, db }: EventHandlerArgs): Promise<true | undefined>;
    /**
     * Handle attestation event
     * @param args `EventHandlerArgs` type arguments.
     * @returns True if succeeds, false otherwise.
     */
    handleAttestation({ decodedData, event, db }: EventHandlerArgs): Promise<true | undefined>;
    /**
     * Handle user state transition event
     * @param args `EventHandlerArgs` type arguments.
     * @returns True if succeeds, false otherwise.
     */
    handleUserStateTransitioned({ decodedData, event, db, }: EventHandlerArgs): Promise<true | undefined>;
    /**
     * Handle epoch ended event
     * @param args `EventHandlerArgs` type arguments.
     * @returns True if succeeds, false otherwise.
     */
    handleEpochEnded({ decodedData, event, db }: EventHandlerArgs): Promise<true | undefined>;
    /**
     * Handle attester signup event
     * @param args `EventHandlerArgs` type arguments.
     * @returns True if succeeds, false otherwise.
     */
    handleAttesterSignedUp({ decodedData, event, db }: EventHandlerArgs): Promise<true | undefined>;
    /**
     * Handle history tree leaf event
     * @param args `EventHandlerArgs` type arguments.
     * @returns True if succeeds, false otherwise.
     */
    handleHistoryTreeLeaf({ decodedData, event, db }: EventHandlerArgs): Promise<true | undefined>;
}
export {};
