import { Address } from 'viem';
import { TransactionRequest, Provider } from '@ethersproject/abstract-provider';
import { BigNumber } from '@ethersproject/bignumber';
import { JsonRpcProvider } from '@ethersproject/providers';
import { Contract } from '@ethersproject/contracts';
import { Signer } from '@ethersproject/abstract-signer';

declare const AddressZero = "0x0000000000000000000000000000000000000000";
declare const EthAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
declare const HashZero = "0x0000000000000000000000000000000000000000000000000000000000000000";
declare const ZeroExV2AllowanceHolderContract = "0x0000000000001fF3684f28c67538d4D072C22734";

declare enum ChainId {
    Mainnet = 1,
    Optimism = 10,
    Polygon = 137,
    Base = 8453,
    Arbitrum = 42161
}

declare const Contracts: {
    [key: number]: {
        [key: string]: Address;
    };
};
declare const IndexDebtIssuanceModuleV2Address_v2 = "0x04b59F9F09750C044D7CfbC177561E409085f0f3";
declare const BasicIssuanceModuleAddress = "0xd8EF3cACe8b4907117a45B0b125c68560532F94D";
declare const BasicIssuanceModulePolygonAddress = "0x38E5462BBE6A72F79606c1A0007468aA4334A92b";
declare const DebtIssuanceModuleV2Address = "0x69a592D2129415a4A1d1b1E309C17051B7F28d57";

declare const noopSwapData: {
    path: string[];
    fees: number[];
    pool: string;
    exchange: number;
};

interface Token {
    symbol: string;
    address?: string;
    addressArbitrum?: string;
    addressBase?: string;
    addressOptimism?: string;
    addressPolygon?: string;
    decimals?: number;
}
declare const DefiPulseIndex: Token;
declare const IndexCoopBitcoin2xIndex: Token;
declare const IndexCoopBitcoin3xIndex: Token;
declare const IndexCoopEthereum2xIndex: Token;
declare const IndexCoopEthereum3xIndex: Token;
declare const InterestCompoundingETHIndex: Token;
declare const MetaverseIndex: Token;
declare const ETH: {
    symbol: string;
    address: string;
    decimals: number;
};
declare const stETH: Token;
declare const USDC: Token;
declare const WETH: Token;

declare enum Exchange {
    None = 0,
    Quickswap = 1,
    Sushiswap = 2,
    UniV3 = 3,
    Curve = 4,
    BalancerV2 = 5,
    Aerodrome = 6,
    AerodromeSlipstream = 7
}
interface SwapData {
    exchange: Exchange;
    path: string[];
    fees: number[];
    pool: string;
}
interface SwapDataV2 {
    swapTarget: string;
    callData: string;
}
interface SwapDataV5 {
    exchange: Exchange;
    path: string[];
    fees: number[];
    pool: string;
    poolIds: string[];
    tickSpacing: number[];
}

interface BuildRequest {
    isMinting: boolean;
    inputToken: string;
    outputToken: string;
    inputTokenSymbol: string;
    outputTokenSymbol: string;
    inputTokenAmount: BigNumber;
    outputTokenAmount: BigNumber;
}
interface TransactionBuilder<R, T> {
    build(request: R): Promise<T | null>;
}

interface FlashMintHyEthBuildRequest extends BuildRequest {
    componentsSwapData: SwapData[];
    swapDataInputTokenToEth: SwapData | null;
    swapDataEthToInputOutputToken: SwapData | null;
}
declare class FlashMintHyEthTransactionBuilder implements TransactionBuilder<FlashMintHyEthBuildRequest, TransactionRequest> {
    private readonly rpcUrl;
    constructor(rpcUrl: string);
    build(request: FlashMintHyEthBuildRequest): Promise<TransactionRequest | null>;
    private isValidRequest;
}

declare const FlashMintAbis: {
    [key: Address]: any;
};

declare function getTokenAddressOrWeth(token: string, chainId: number): Address;
declare function isZeroExV2AllowanceHolderContract(address?: string): boolean;

/**
 * Returns an instance of a FlashMintHyEth contract.
 * Currently, only Mainnet is supported.
 */
declare const getFlashMintHyEthContract: (signerOrProvider: Signer | Provider | undefined) => Contract;
/**
 * Returns an instance of a FlashMintZeroEx contract.
 *
 * @param providerSigner A provider or signer.
 * @returns An instance of a FlashMintZeroEx contract.
 */
declare const getFlashMintZeroExContract: (providerSigner: Signer | Provider | undefined) => Contract;
/**
 * Returns the FlashMintZeroEx contract based on the token.
 *
 * @param token The token to be minted/redeemed.
 * @param providerSigner A provider or signer.
 * @returns An instance of a FlashMintZeroEx contract.
 */
declare const getFlashMintZeroExContractForToken: (token: string, providerSigner: Signer | Provider | undefined) => Contract;
declare function getFlashMintContract(contract: Address, providerSigner: Signer | Provider | undefined): Contract;

interface IssuanceModule {
    address: string;
    isDebtIssuance: boolean;
}
declare function getIssuanceModule(tokenSymbol: string, chainId?: number): IssuanceModule;

declare const wei: (input: number | string, power?: number) => BigNumber;

/**
 * Returns slippage adjusted token amount based on minting/redeeming.
 * @param tokenAmount     The token amount to be adjusted
 * @param tokenDecimals   The token's decimals
 * @param slippage        The slippage in percent: 0.1 - 100
 * @param isMinting       Whether minting or redeeming
 */
declare function slippageAdjustedTokenAmount(tokenAmount: BigNumber, tokenDecimals: number, slippage: number, isMinting: boolean): BigNumber;

interface FlashMintLeveragedZeroExBuilderBuildRequest extends BuildRequest {
    chainId: number;
    swapDataDebtCollateral: SwapDataV2;
    swapDataInputOutputToken: SwapDataV2;
    isAave: boolean;
}
declare class LeveragedZeroExBuilder implements TransactionBuilder<FlashMintLeveragedZeroExBuilderBuildRequest, TransactionRequest> {
    private readonly rpcUrl;
    constructor(rpcUrl: string);
    build(request: FlashMintLeveragedZeroExBuilderBuildRequest): Promise<TransactionRequest | null>;
    private isValidRequest;
}

interface FlashMintZeroExBuildRequest {
    isMinting: boolean;
    indexToken: string;
    indexTokenSymbol: string;
    inputOutputToken: string;
    inputOutputTokenSymbol: string;
    indexTokenAmount: BigNumber;
    inputOutputTokenAmount: BigNumber;
    componentQuotes: string[];
}
declare class ZeroExTransactionBuilder implements TransactionBuilder<FlashMintZeroExBuildRequest, TransactionRequest> {
    private readonly rpcUrl;
    constructor(rpcUrl: string);
    build(request: FlashMintZeroExBuildRequest): Promise<TransactionRequest | null>;
    private isValidRequest;
}

interface QuoteProvider<R, Q> {
    getQuote(request: R): Promise<Q | null>;
}
interface QuoteToken {
    address: string;
    decimals: number;
    symbol: string;
}

interface SwapPriceQuoteV2 {
    chainId: number;
    inputToken: string;
    outputToken: string;
    inputAmount: string;
    outputAmount: string;
    slippage: number;
}
interface SwapQuoteV2 {
    chainId: number;
    inputToken: string;
    outputToken: string;
    inputAmount: string;
    outputAmount: string;
    slippage: number;
    swapData: SwapDataV2 | null;
}
interface SwapPriceRequestV2 {
    chainId: number;
    inputToken: string;
    outputToken: string;
    inputAmount: string;
    slippage: number;
    sellEntireBalance: boolean;
    taker?: string;
}
interface SwapQuoteRequestV2 {
    chainId: number;
    inputToken: string;
    outputToken: string;
    inputAmount?: string;
    outputAmount?: string;
    slippage: number;
    taker: string;
    sellEntireBalance?: boolean;
    sources?: Exchange[];
}
interface SwapQuoteProviderV2 {
    getSwapQuote(request: SwapQuoteRequestV2): Promise<SwapQuoteV2 | null>;
}

declare class LiFiSwapQuoteProvider implements SwapQuoteProviderV2 {
    readonly apiKey: string;
    readonly integrator: string;
    constructor(apiKey: string, integrator: string);
    getSwapQuote(request: SwapQuoteRequestV2): Promise<SwapQuoteV2 | null>;
}

declare class ZeroExV2SwapQuoteProvider implements SwapQuoteProviderV2 {
    readonly apiKey: string;
    constructor(apiKey: string);
    getPriceQuote(request: SwapPriceRequestV2): Promise<SwapPriceQuoteV2 | null>;
    getSwapQuote(request: SwapQuoteRequestV2): Promise<SwapQuoteV2 | null>;
    getPath(request: SwapQuoteRequestV2 | SwapPriceRequestV2): string;
}

interface FlashMintHyEthQuoteRequest {
    isMinting: boolean;
    inputToken: QuoteToken;
    outputToken: QuoteToken;
    indexTokenAmount: bigint;
    inputAmount: bigint;
    slippage: number;
}
interface FlashMintHyEthQuote {
    indexTokenAmount: bigint;
    inputOutputTokenAmount: bigint;
    componentsSwapData: SwapData[];
    swapDataInputTokenToEth: SwapData | null;
    swapDataEthToInputOutputToken: SwapData | null;
}
declare class FlashMintHyEthQuoteProvider implements QuoteProvider<FlashMintHyEthQuoteRequest, FlashMintHyEthQuote> {
    private readonly rpcUrl;
    private readonly swapQuoteProvider;
    private readonly swapQuoteOutputProvider?;
    constructor(rpcUrl: string, swapQuoteProvider: SwapQuoteProviderV2, swapQuoteOutputProvider?: SwapQuoteProviderV2 | undefined);
    getQuote(request: FlashMintHyEthQuoteRequest): Promise<FlashMintHyEthQuote | null>;
}

interface FlashMintLeveragedZeroExQuoteRequest {
    chainId: number;
    isMinting: boolean;
    inputToken: QuoteToken;
    outputToken: QuoteToken;
    inputAmount: string;
    outputAmount: string;
    slippage: number;
    taker: string;
}
interface FlashMintLeveragedZeroExQuote {
    inputAmount: string;
    outputAmount: string;
    swapDataDebtCollateral: SwapDataV2;
    swapDataInputOutputToken: SwapDataV2;
    isAave: boolean;
}
declare class LeveragedZeroExQuoteProvider implements QuoteProvider<FlashMintLeveragedZeroExQuoteRequest, FlashMintLeveragedZeroExQuote> {
    private readonly rpcUrl;
    private readonly swapQuoteProvider;
    private readonly swapQuoteOutputProvider?;
    constructor(rpcUrl: string, swapQuoteProvider: SwapQuoteProviderV2, swapQuoteOutputProvider?: SwapQuoteProviderV2 | undefined);
    getQuote(request: FlashMintLeveragedZeroExQuoteRequest): Promise<FlashMintLeveragedZeroExQuote | null>;
    private getSwapDataCollateralToDebt;
    private getSwapDataDebtToCollateral;
    private getSwapDataInputOutputToken;
}

interface FlashMintZeroExQuoteRequest {
    isMinting: boolean;
    inputToken: QuoteToken;
    outputToken: QuoteToken;
    indexTokenAmount: BigNumber;
    slippage: number;
}
interface FlashMintZeroExQuote {
    componentQuotes: string[];
    indexTokenAmount: BigNumber;
    inputOutputTokenAmount: BigNumber;
}
declare class ZeroExQuoteProvider implements QuoteProvider<FlashMintZeroExQuoteRequest, FlashMintZeroExQuote> {
    private readonly rpcUrl;
    private readonly swapQuoteProvider;
    constructor(rpcUrl: string, swapQuoteProvider: SwapQuoteProviderV2);
    getQuote(request: FlashMintZeroExQuoteRequest): Promise<FlashMintZeroExQuote | null>;
}
/**
 * Returns the required component and position quotes depending on minting/redeeming.
 * @param isMinting         Whether minting or redeeming
 * @param indexToken        Address of the Index token
 * @param indexTokenSymbol  Symbol of the Index token
 * @param indexTokenAmount  Amount of the Index token
 * @param provider          An instance of JsonRpcProvider
 * @param chainId           ID of the network
 */
declare function getRequiredComponents(isMinting: boolean, indexToken: string, indexTokenSymbol: string, indexTokenAmount: BigNumber, provider: JsonRpcProvider, chainId: number): Promise<{
    components: any;
    positions: any;
}>;

declare enum FlashMintContractType {
    hyeth = 0,
    leveragedZeroEx = 1,
    zeroEx = 2
}
interface FlashMintQuoteRequest {
    chainId: number;
    isMinting: boolean;
    inputToken: QuoteToken;
    outputToken: QuoteToken;
    indexTokenAmount: string;
    inputTokenAmount?: string;
    slippage: number;
}
interface FlashMintQuote {
    chainId: number;
    contractType: FlashMintContractType;
    contract: string;
    isMinting: boolean;
    inputToken: QuoteToken;
    outputToken: QuoteToken;
    inputAmount: BigNumber;
    outputAmount: BigNumber;
    indexTokenAmount: BigNumber;
    inputOutputAmount: BigNumber;
    slippage: number;
    tx: TransactionRequest;
}
declare class FlashMintQuoteProvider implements QuoteProvider<FlashMintQuoteRequest, FlashMintQuote> {
    private readonly rpcUrl;
    private readonly swapQuoteProviderV2;
    private readonly swapQuoteOutputProviderV2?;
    constructor(rpcUrl: string, swapQuoteProviderV2: SwapQuoteProviderV2, swapQuoteOutputProviderV2?: SwapQuoteProviderV2 | undefined);
    getQuote(request: FlashMintQuoteRequest): Promise<FlashMintQuote | null>;
}

export { AddressZero, BasicIssuanceModuleAddress, BasicIssuanceModulePolygonAddress, BuildRequest, ChainId, Contracts, DebtIssuanceModuleV2Address, DefiPulseIndex, ETH, EthAddress, Exchange, FlashMintAbis, FlashMintContractType, FlashMintHyEthBuildRequest, FlashMintHyEthQuote, FlashMintHyEthQuoteProvider, FlashMintHyEthQuoteRequest, FlashMintHyEthTransactionBuilder, FlashMintLeveragedZeroExBuilderBuildRequest, FlashMintLeveragedZeroExQuote, FlashMintLeveragedZeroExQuoteRequest, FlashMintQuote, FlashMintQuoteProvider, FlashMintQuoteRequest, FlashMintZeroExBuildRequest, FlashMintZeroExQuote, FlashMintZeroExQuoteRequest, HashZero, IndexCoopBitcoin2xIndex, IndexCoopBitcoin3xIndex, IndexCoopEthereum2xIndex, IndexCoopEthereum3xIndex, IndexDebtIssuanceModuleV2Address_v2, InterestCompoundingETHIndex, IssuanceModule, LeveragedZeroExBuilder, LeveragedZeroExQuoteProvider, LiFiSwapQuoteProvider, MetaverseIndex, QuoteProvider, QuoteToken, SwapData, SwapDataV2, SwapDataV5, SwapPriceQuoteV2, SwapPriceRequestV2, SwapQuoteProviderV2, SwapQuoteRequestV2, SwapQuoteV2, Token, TransactionBuilder, USDC, WETH, ZeroExQuoteProvider, ZeroExTransactionBuilder, ZeroExV2AllowanceHolderContract, ZeroExV2SwapQuoteProvider, getFlashMintContract, getFlashMintHyEthContract, getFlashMintZeroExContract, getFlashMintZeroExContractForToken, getIssuanceModule, getRequiredComponents, getTokenAddressOrWeth, isZeroExV2AllowanceHolderContract, noopSwapData, slippageAdjustedTokenAmount, stETH, wei };
