import * as uma from "@uma/sdk";
import { BigNumber, BigNumberish } from "../utils";
import { Signer } from "ethers";
import type { Overrides } from "@ethersproject/contracts";
import { TransactionRequest, TransactionReceipt, Log } from "@ethersproject/abstract-provider";
import { Provider, Block } from "@ethersproject/providers";
import { hubPool } from "../contracts";
import { AcceleratingDistributor, MerkleDistributor } from "../typechain";
export type { Provider };
export type Awaited<T> = T extends PromiseLike<infer U> ? U : T;
export type Config = {
    chainId?: number;
    hubPoolAddress: string;
    acceleratingDistributorAddress: string;
    merkleDistributorAddress: string;
    wethAddress: string;
    configStoreAddress: string;
    confirmations?: number;
    blockDelta?: number;
    hasArchive?: boolean;
    hubPoolStartBlock?: number;
};
export type Dependencies = {
    provider: Provider;
};
export type StakeData = {
    cumulativeBalance: BigNumber;
    amountAirdropped: BigNumber;
};
export type Pool = {
    address: string;
    totalPoolSize: string;
    l1Token: string;
    lpToken: string;
    liquidReserves: string;
    exchangeRateCurrent: string;
    exchangeRatePrevious: string;
    estimatedApy: string;
    estimatedApr: string;
    blocksElapsed: number;
    secondsElapsed: number;
    utilizedReserves: string;
    projectedApr: string;
    liquidityUtilizationCurrent: string;
};
export type User = {
    address: string;
    poolAddress: string;
    lpTokens: string;
    positionValue: string;
    totalDeposited: string;
    feesEarned: string;
};
export type Transaction = {
    id: string;
    state: "requested" | "submitted" | "mined" | "error";
    toAddress: string;
    fromAddress: string;
    type: "Add Liquidity" | "Remove Liquidity";
    description: string;
    request?: TransactionRequest;
    hash?: string;
    receipt?: TransactionReceipt;
    error?: Error;
};
export type Token = {
    decimals: string;
    symbol: string;
    name: string;
};
export type State = {
    pools: Record<string, Pool>;
    users: Record<string, Record<string, User>>;
    transactions: Record<string, Transaction>;
    error?: Error;
};
export type EmitState = (path: string[], data: Pool | User | Transaction | Error) => void;
export type PooledToken = {
    lpToken: string;
    isEnabled: boolean;
    lastLpFeeUpdate: number;
    utilizedReserves: BigNumber;
    liquidReserves: BigNumber;
    undistributedLpFees: BigNumber;
};
type EventIdParams = {
    blockNumber: number;
    transactionIndex: number;
    logIndex: number;
};
export declare class PoolEventState {
    private contract;
    private startBlock;
    private seen;
    private iface;
    private events;
    constructor(contract: hubPool.Instance, startBlock?: number);
    private makeId;
    hasEvent(params: EventIdParams): boolean;
    private addEvent;
    private filterSeen;
    private processEvent;
    private processEvents;
    read(endBlock: number, l1TokenAddress?: string, userAddress?: string): Promise<hubPool.EventState>;
    makeEventFromLog: (log: Log) => uma.SerializableEvent;
    getL1TokenFromReceipt(receipt: TransactionReceipt): string;
    readTxReceipt(receipt: TransactionReceipt): hubPool.EventState;
}
declare class UserState {
    private contract;
    private userAddress;
    private startBlock;
    private acceleratingDistributorContractAddress;
    private seen;
    private events;
    constructor(contract: uma.clients.erc20.Instance, userAddress: string, startBlock?: number, acceleratingDistributorContractAddress?: string);
    private makeId;
    hasEvent(params: EventIdParams): boolean;
    private addEvent;
    private filterSeen;
    /**
     * readEvents. Fetch and cache events for the user.
     *
     * @param {number} endBlock
     */
    readEvents(endBlock: number): Promise<uma.clients.erc20.Transfer[]>;
    /**
     * read. Reads the state for the user, building state from events as well as contract calls.
     *
     * @param {number} endBlock
     */
    read(endBlock: number): Promise<{
        transferEvents: import("@uma/contracts-frontend").TypedEventEthers<[string, string, uma.oracle.types.ethers.BigNumber] & {
            from: string;
            to: string;
            value: uma.oracle.types.ethers.BigNumber;
        }>[];
        balanceTransferred: string;
        address: string;
        balanceOf: uma.oracle.types.ethers.BigNumber;
    }>;
}
export declare function calculateRemoval(amountWei: BigNumber, percentWei: BigNumber): {
    receive: string;
    remain: string;
};
export declare function previewRemoval(values: {
    positionValue: BigNumberish;
    feesEarned: BigNumberish;
    totalDeposited: BigNumberish;
}, percentFloat: number): {
    position: {
        receive: string;
        remain: string;
    };
    fees: {
        receive: string;
        remain: string;
    };
    total: {
        receive: string;
        remain: string;
    };
};
export declare class ReadPoolClient {
    private address;
    private provider;
    private poolState;
    private contract;
    constructor(address: string, provider: Provider);
    read(tokenAddress: string, latestBlock: number): Promise<{
        lpToken: string;
        isEnabled: boolean;
        lastLpFeeUpdate: number;
        utilizedReserves: uma.oracle.types.ethers.BigNumber;
        liquidReserves: uma.oracle.types.ethers.BigNumber;
        undistributedLpFees: uma.oracle.types.ethers.BigNumber;
        address: string;
        l1Token: string;
        latestBlock: number;
        previousBlock: number | undefined;
        exchangeRatePrevious: uma.oracle.types.ethers.BigNumber;
        exchangeRateCurrent: uma.oracle.types.ethers.BigNumber;
        liquidityUtilizationCurrent: uma.oracle.types.ethers.BigNumber;
    }>;
}
export declare function validateWithdraw(pool: Pool, user: User, lpTokenAmount: BigNumberish): {
    lpTokenAmount: uma.oracle.types.ethers.BigNumberish;
    l1TokensToReturn: string;
};
export declare class Client {
    readonly config: Config;
    readonly deps: Dependencies;
    private emit;
    private transactionManagers;
    private hubPool;
    private acceleratingDistributor;
    private merkleDistributor;
    readonly state: State;
    private poolEvents;
    private erc20s;
    private intervalStarted;
    private configStoreClient;
    private exchangeRateTable;
    private userServices;
    constructor(config: Config, deps: Dependencies, emit: EmitState);
    getOrCreateErc20Contract(address: string): uma.clients.erc20.Instance;
    getOrCreatePoolContract(): hubPool.Instance;
    createHubPoolContract(signerOrProvider: Signer | Provider): hubPool.Instance;
    private getOrCreatePoolEvents;
    createAcceleratingDistributorContract(signerOrProvider: Signer | Provider): AcceleratingDistributor;
    createMerkleDistributorContract(signerOrProvider: Signer | Provider): MerkleDistributor;
    getOrCreateAcceleratingDistributorContract(): AcceleratingDistributor;
    getOrCreateMerkleDistributorContract(): MerkleDistributor;
    private getOrCreateUserService;
    private updateExchangeRateTable;
    resolveStakingData(lpToken: string, l1TokenAddress: string, userState: Awaited<ReturnType<UserState["read"]>>): Promise<StakeData>;
    calculateLpTransferValue(l1TokenAddress: string, userState: Awaited<ReturnType<UserState["read"]>>): Promise<uma.oracle.types.ethers.BigNumber>;
    private getOrCreateTransactionManager;
    addEthLiquidity(signer: Signer, l1TokenAmount: BigNumberish, overrides?: Overrides): Promise<string>;
    addTokenLiquidity(signer: Signer, l1Token: string, l1TokenAmount: BigNumberish, overrides?: Overrides): Promise<string>;
    validateWithdraw(l1Token: string, userAddress: string, lpAmount: BigNumberish): Promise<{
        lpTokenAmount: uma.oracle.types.ethers.BigNumberish;
        l1TokensToReturn: string;
    }>;
    removeTokenLiquidity(signer: Signer, l1Token: string, lpTokenAmount: BigNumberish, overrides?: Overrides): Promise<string>;
    removeEthliquidity(signer: Signer, lpTokenAmount: BigNumberish, overrides?: Overrides): Promise<string>;
    getPoolState(l1TokenAddress: string): Pool;
    hasPoolState(l1TokenAddress: string): boolean;
    setUserState(l1TokenAddress: string, userAddress: string, state: User): User;
    getUserState(l1TokenAddress: string, userAddress: string): User;
    hasUserState(l1TokenAddress: string, userAddress: string): boolean;
    hasTxState(id: string): boolean;
    getTxState(id: string): Transaction;
    private updateAndEmitUser;
    private updateUserWithTransaction;
    updateUser(userAddress: string, l1TokenAddress: string): Promise<void>;
    updatePool(l1TokenAddress: string, overrideLatestBlock?: Block): Promise<void>;
    updateTransactions(): Promise<void>;
    startInterval(delayMs?: number): void;
    stopInterval(): void;
}
