import { ethers } from 'ethers';
import { DB } from 'anondb';
import { Identity } from '@semaphore-protocol/identity';
import { Prover, ReputationProof, EpochKeyProof, SignupProof, UserStateTransitionProof, EpochKeyLiteProof } from '@unirep/circuits';
import { Synchronizer } from './Synchronizer';
/**
 * The user state object is used to manage user state for an attester.
 * The state is backed by an [anondb](https://github.com/vimwitch/anondb) instance.
 * @example
 * ```ts
 * import { UserState } from '@unirep/core'
 * import { defaultProver } from '@unirep/circuits/provers/defaultProver'
 * import { Identity } from '@semaphore-protocol/identity'
 *
 * const id = new Identity()
 * const state = new UserState({
 *   prover: defaultProver, // a circuit prover
 *   unirepAddress: '0xaabbccaabbccaabbccaabbccaabbccaabbccaaaa',
 *   provider, // an ethers.js provider
 *   id,
 * })
 *
 * // or, initialize with an existing synchronizer object
 * const state = new UserState({
 *   synchronizer,
 *   id,
 *   prover: defaultProver, // a circuit prover
 * })
 *
 * // start the synchoronizer deamon
 * await state.start()
 * await state.waitForSync()
 *
 * // stop the synchronizer deamon
 * state.stop()
 * ```
 */
export default class UserState {
    private _prover;
    private _id;
    private _sync;
    private _chainId;
    private _db;
    /**
     * The [Semaphore](https://semaphore.pse.dev/) identity commitment of the user.
     */
    get commitment(): bigint;
    /**
     * The [Semaphore](https://semaphore.pse.dev/) identity of the user.
     */
    get id(): Identity;
    /**
     * The underlying synchronizer object.
     */
    get sync(): Synchronizer;
    /**
     * The prover object.
     */
    get prover(): Prover;
    /**
     * The current chain ID of UniRep contract.
     */
    get chainId(): number;
    /**
     * Read the database object.
     */
    get db(): DB;
    constructor(config: {
        synchronizer?: Synchronizer;
        db?: DB;
        attesterId?: bigint | bigint[];
        unirepAddress?: string;
        provider?: ethers.providers.Provider;
        id: Identity;
        prover: Prover;
    });
    /**
     * 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>;
    /**
     * 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>;
    /**
     * Stop synchronizing with Unirep contract.
     */
    stop(): void;
    /**
     * Query the current database if the [Semaphore](https://semaphore.pse.dev/) identity commitment is stored.
     * @param attesterId The attester to be queried. Default: `this.attesterId`.
     * @returns True if user has signed up in unirep contract, false otherwise.
     */
    hasSignedUp(attesterId?: bigint | string): Promise<boolean>;
    /**
     * Query the current database for a user's signup event or latest user state transition [nullifier](https://developer.unirep.io/docs/protocol/nullifiers).
     * @param attesterId The attester to be queried. Default: `this.attesterId`
     * @returns The latest epoch where a user performed a user state transition.
     */
    latestTransitionedEpoch(attesterId?: bigint | string): Promise<number>;
    /**
     * Get the latest global state tree leaf index for an epoch.
     * @param epoch Get the global state tree leaf index of the given epoch. Default: current epoch.
     * @param attesterId The attester to be queried. Default: `this.attesterId`
     * @returns The the latest state tree leaf index for an epoch.
     */
    latestStateTreeLeafIndex(epoch?: number, attesterId?: bigint | string): Promise<number>;
    /**
     * Get epoch keys for the current user, for an epoch.
     * If a `nonce` value is supplied the return value will be a single epoch key.
     * Otherwise an array of all epoch keys will be returned.
     *
     * If no `epoch` is supplied the current epoch will be used (as determined by `synchronizer.calcCurrentEpoch`).
     * @param epoch The epoch to be queried. Default: current epoch.
     * @param nonce The specified epoch key nonce. Default: `0`.
     * @param attesterId The attester to be queried. Default: `this.attesterId`
     * @returns An epoch key or an array of epoch keys.
     */
    getEpochKeys(epoch?: bigint | number, nonce?: number, attesterId?: bigint | string): bigint | bigint[];
    /**
     * This function is used to parse replacement data field to be `index` and `data`. See [replacement data field](https://developer.unirep.io/docs/protocol/data#replacement-field).
     * @param replData The raw data which is processed on-chain.
     * @returns The parsed data and the data index (nonce).
     */
    parseReplData(replData: bigint): {
        data: bigint;
        nonce: bigint;
    };
    /**
     * @private
     * Update user state data.
     * @param data The latest transitioned data.
     * @param latestTransitionedEpoch The latest found transitioned epoch.
     * @param attesterId The attester ID.
     */
    private _updateData;
    /**
     * Get the data for a user up to and including the provided epoch.
     * By default data up to and including the current epoch is returned.
     *
     * :::tip
     * If you want to make a proof of data make sure to use `getProvableData`.
     * Data can only be proven once it has been included in a state tree leaf.
     * Learn more about reputation proofs [here](https://developer.unirep.io/docs/circuits-api/classes/src.ReputationProof.md).
     * :::
     * @param toEpoch The latest epoch that the reputation is accumulated. Default: current epoch.
     * @param attesterId The attester to be queried. Default: `this.sync.attesterId`
     * @param fromEpoch The epoch to start querying from. Default: `0`.
     * @returns The data object
     */
    getData: (toEpoch?: number, attesterId?: bigint | string) => Promise<bigint[]>;
    /**
     * Get the data that can be proven by the user using a state tree leaf.
     * This is the data up to, but not including, the epoch the user has transitioned into.
     * @param attesterId The attester to be queried. Default: `this.attesterId`
     * @returns The data object
     */
    getProvableData(attesterId?: bigint | string): Promise<bigint[]>;
    /**
     * Get the pending changes to the data owned by an epoch key.
     * @param epochKey The epoch key to be queried.
     * @param epoch The epoch of the epoch key to be queried.
     * @param attesterId The attester to be queried. Default: `this.attesterId`
     * @returns The data object.
     */
    getDataByEpochKey: (epochKey: bigint | string, epoch: number, attesterId?: bigint | string) => Promise<any[]>;
    /**
     * @private
     * Check if epoch key nonce is valid. Throws an error if the epoch key nonce is invalid.
     * @param epochKeyNonce The input epoch key nonce to be checked.
     */
    private _checkEpkNonce;
    /**
     * @private
     * Check if a synchronizer is set. Throws an error if a synchronizer is not set.
     */
    private _checkSync;
    /**
     * @private
     * Check if a chain ID is set. If a chain ID is not set, it queries the provider and sets chain ID.
     */
    private _checkChainId;
    /**
     * @private
     * Check if the input exceeds the maximum bit
     * @param input The input value
     * @param bit The bit number
     */
    private _checkBit;
    /**
     * Get the index of epoch key among all attestations.
     * @param epoch The epoch of the epoch key to be queried.
     * @param epochKey The epoch key to be queried.
     * @param attesterId The attester to be queried.
     * @returns The index of the epoch key.
     */
    getEpochKeyIndex: (epoch: number, epochKey: bigint | string, attesterId: bigint | string) => Promise<number>;
    /**
     * Generate a user state transition proof. Returns a [`UserStateTransitionProof`](https://developer.unirep.io/docs/circuits-api/classes/src.UserStateTransitionProof.md).
     * @param options.toEpoch `toEpoch` is used to indicate in which epoch the proof will be used. Default: current epoch.
     * @param options.attesterId `attesterId` is used to generate proof for certain attester. Default: `this.attesterId`.
     * @returns The `UserStateTransitionProof` object.
     * @example
     * ```ts
     * const { publicSignals, proof } = await userState.genUserStateTransitionProof()
     * ```
     */
    genUserStateTransitionProof: (options?: {
        toEpoch?: number;
        attesterId?: bigint | string;
    }) => Promise<UserStateTransitionProof>;
    /**
     * Generate a proof of reputation. Returns a [`ReputationProof`](https://developer.unirep.io/docs/circuits-api/classes/src.ReputationProof.md).
     * :::danger
     * **Please avoid assigning the `minRep = data[0] - data[1]` or `maxRep = data[1] - data[0]`.**<br/>
     * The proof could allow a user to accidentally publish their overall reputation (i.e. `data[0]-data[1]`).
     * Depending on the circumstances (such as the length of the attestation history) this could reveal a user’s epoch key(s) as well.
     * :::
     * @param options.epkNonce The nonce determines the output of the epoch key. Default: `0`.
     * @param options.minRep The amount of reputation that user wants to prove. It should satisfy: `posRep - negRep >= minRep`. Default: `0`
     * @param options.maxRep The amount of reputation that user wants to prove. It should satisfy: `negRep - posRep >= maxRep`. Default: `0`
     * @param options.graffiti The graffiti that user wants to prove. It should satisfy: `graffiti == (data[SUM_FIELD_COUNT] / (2 ** REPL_NONCE_BITS))`. Default: `0`.
     * @param options.proveZeroRep Indicates if user wants to prove `posRep - negRep == 0`. Default: `0`.
     * @param options.revealNonce Indicates if user wants to reveal epoch key nonce. Default: `false`.
     * @param options.data Indicates if user wants to endorse a 253-bits data. Default: `0`.
     * @param options.attesterId `attesterId` is used to generate proof for certain attester. Default: `this.attesterId`
     * @returns The reputation proof of type `ReputationProof`.
     * @example
     * ```ts
     * const {publicSignals, proof} = await userState.genProveReputationProof({
     *   minRep: 3,
     *   graffiti: '1234',
     * })
     * ```
     */
    genProveReputationProof: (options: {
        epkNonce?: number;
        minRep?: number | bigint | string;
        maxRep?: number | bigint | string;
        graffiti?: bigint | string;
        proveZeroRep?: boolean;
        revealNonce?: boolean;
        data?: bigint | string;
        attesterId?: bigint | string;
    }) => Promise<ReputationProof>;
    /**
     * Generate a proof that can be used to signup. Returns a [`SignupProof`](https://developer.unirep.io/docs/circuits-api/classes/src.SignupProof.md)
     * @param options.epoch Indicates in which epoch the proof will be used. Default: current epoch.
     * @param options.attesterId Indicates for which attester the proof will be used. Default: `this.attesterId`
     * @returns The sign up proof of type `SignUpProof`.
     * @example
     * ```ts
     * const { publicSignals, proof } = await userState.genUserSignUpProof()
     * ```
     */
    genUserSignUpProof: (options?: {
        epoch?: number;
        attesterId?: bigint | string;
    }) => Promise<SignupProof>;
    /**
     * Generate a proof that a user controls an epoch key in a certain epoch.
     * Optionally provide a data value to sign.
     * Returns an [`EpochKeyProof`](https://developer.unirep.io/docs/circuits-api/classes/src.EpochKeyProof.md).
     * @param options.nonce The specified epoch key nonce. Default: `0`.
     * @param options.epoch The specified epoch. Default: current epoch.
     * @param options.data Indicates if user wants to endorse a 253-bits data. Default: `0`
     * @param options.revealNonce Indicates if user wants to reveal epoch key nonce. Default: `false`.
     * @param options.attesterId Indicates for which attester the proof will be used. Default: `this.attesterId`
     * @returns The epoch key proof of type `EpochKeyProof`.
     * @example
     * ```ts
     * const { publicSignals, proof } = await userState.genEpochKeyProof({
     *   nonce: 1
     * })
     * ```
     */
    genEpochKeyProof: (options?: {
        nonce?: number;
        epoch?: number;
        data?: bigint;
        revealNonce?: boolean;
        attesterId?: bigint | string;
    }) => Promise<EpochKeyProof>;
    /**
     * Generate a proof that a user controls an epoch key in a certain epoch.
     * Optionally provide a data value to sign.
     * Returns an [`EpochKeyLiteProof`](https://developer.unirep.io/docs/circuits-api/classes/src.EpochKeyLiteProof.md).
     *
     * This proof **will not include a merkle tree proof** which makes the proof size smaller than an [`EpochKeyProof`](https://developer.unirep.io/docs/circuits-api/classes/src.EpochKeyProof.md).
     * It can be used to prove a seen and valid epoch key.
     * @param options.nonce The specified epoch key nonce. Default: `0`.
     * @param options.epoch The specified epoch. Default: current epoch.
     * @param options.data Indicates if user wants to endorse a 253-bits data. Default: `0`.
     * @param options.revealNonce Indicates if user wants to reveal epoch key nonce. Default: `false`.
     * @param options.attesterId Indicates for which attester the proof will be used. Default: `this.attesterId`
     * @returns The epoch key lite proof of type `EpochKeyLiteProof`.
     * @example
     * ```ts
     * const { publicSignals, proof } = await userState.genEpochKeyLiteProof({
     *   nonce: 1
     * })
     * ```
     */
    genEpochKeyLiteProof: (options?: {
        nonce?: number;
        epoch?: number;
        data?: bigint;
        revealNonce?: boolean;
        attesterId?: bigint | string;
    }) => Promise<EpochKeyLiteProof>;
}
export { UserState };
