import { Offer, Errors } from '@morpho-dev/mempool';
export * from '@morpho-dev/mempool';
import * as viem from 'viem';
import { Address, Account, Hex, PublicClient } from 'viem';
import { Chain as Chain$2 } from 'viem/chains';

type Compute<type> = {
    [key in keyof type]: type[key];
} & unknown;

declare const chainNames: readonly ["ethereum", "base"];
type ChainName = (typeof chainNames)[number];
declare const ChainId: {
    ETHEREUM: bigint;
    BASE: bigint;
};
type ChainId = (typeof ChainId)[keyof typeof ChainId];
declare const chainIds: Set<bigint>;
type Chain = Compute<Omit<Chain$2, "id" | "name"> & {
    id: ChainId;
    name: ChainName;
    whitelistedAssets: Set<Address>;
    morpho: Address;
}>;
declare function getChain(chainId: ChainId): Chain | undefined;
declare const chains: Record<ChainName, Chain>;

type Chain$1_Chain = Chain;
type Chain$1_ChainId = ChainId;
type Chain$1_ChainName = ChainName;
declare const Chain$1_chainIds: typeof chainIds;
declare const Chain$1_chainNames: typeof chainNames;
declare const Chain$1_chains: typeof chains;
declare const Chain$1_getChain: typeof getChain;
declare namespace Chain$1 {
  export { type Chain$1_Chain as Chain, type Chain$1_ChainId as ChainId, type Chain$1_ChainName as ChainName, Chain$1_chainIds as chainIds, Chain$1_chainNames as chainNames, Chain$1_chains as chains, Chain$1_getChain as getChain };
}

declare const OfferStatusValues: readonly ["valid", "callback_not_supported", "callback_error", "unverified"];
type OfferStatus = (typeof OfferStatusValues)[number];
type OfferMetadata = {
    issue: string;
};
type RouterOffer = Offer.Offer & {
    status: OfferStatus;
    metadata?: OfferMetadata;
};

type RouterOffer$1_OfferMetadata = OfferMetadata;
type RouterOffer$1_OfferStatus = OfferStatus;
declare const RouterOffer$1_OfferStatusValues: typeof OfferStatusValues;
type RouterOffer$1_RouterOffer = RouterOffer;
declare namespace RouterOffer$1 {
  export { type RouterOffer$1_OfferMetadata as OfferMetadata, type RouterOffer$1_OfferStatus as OfferStatus, RouterOffer$1_OfferStatusValues as OfferStatusValues, type RouterOffer$1_RouterOffer as RouterOffer };
}

type GetParameters = {
    /** Filter by multiple creator addresses (comma-separated) */
    creators?: string[];
    /** Filter by offer type: buy offers or sell offers */
    side?: "buy" | "sell";
    /** Filter by multiple blockchain networks (comma-separated chain IDs) */
    chains?: number[];
    /** Filter by multiple loan assets (comma-separated) */
    loanTokens?: string[];
    /** Filter by multiple statuses (comma-separated) */
    status?: OfferStatus[];
    /** Filter by multiple callback addresses (comma-separated) */
    callbackAddresses?: string[];
    /** Minimum amount of assets in the offer */
    minAmount?: bigint;
    /** Maximum amount of assets in the offer */
    maxAmount?: bigint;
    /** Minimum rate per asset (in wei) */
    minRate?: bigint;
    /** Maximum rate per asset (in wei) */
    maxRate?: bigint;
    /** Minimum maturity timestamp (Unix timestamp in seconds) */
    minMaturity?: number;
    /** Maximum maturity timestamp (Unix timestamp in seconds) */
    maxMaturity?: number;
    /** Minimum expiry timestamp (Unix timestamp in seconds) */
    minExpiry?: number;
    /** Maximum expiry timestamp (Unix timestamp in seconds) */
    maxExpiry?: number;
    /** Filter by multiple collateral assets (comma-separated) */
    collateralAssets?: string[];
    /** Filter by multiple rate oracles (comma-separated) */
    collateralOracles?: string[];
    /** Filter by collateral combinations */
    collateralTuple?: Array<{
        asset: string;
        oracle?: string;
        lltv?: number;
    }>;
    /** Minimum Loan-to-Value ratio (LLTV) for collateral (percentage as decimal) */
    minLltv?: number;
    /** Maximum Loan-to-Value ratio (LLTV) for collateral (percentage as decimal) */
    maxLltv?: number;
    /** Field to sort results by */
    sortBy?: "rate" | "maturity" | "expiry" | "amount";
    /** Sort direction: asc (ascending) or desc (descending, default) */
    sortOrder?: "asc" | "desc";
    /** Pagination cursor in base64url-encoded format */
    cursor?: string;
    /** Maximum number of offers to return. Defaults to 20. Maximum is 100. */
    limit?: number;
};
type MatchParameters = {
    /** The desired side of the match: 'buy' if you want to buy, 'sell' if you want to sell */
    side: "buy" | "sell";
    /** The blockchain network chain ID */
    chainId: number;
    /** Rate per asset (in wei) for matching offers */
    rate?: bigint;
    /** Collateral requirements */
    collaterals?: Array<{
        asset: string;
        oracle: string;
        lltv: bigint;
    }>;
    /** Exact maturity timestamp (Unix timestamp in seconds) */
    maturity?: number;
    /** Minimum maturity timestamp (Unix timestamp in seconds, inclusive) */
    minMaturity?: number;
    /** Maximum maturity timestamp (Unix timestamp in seconds, inclusive) */
    maxMaturity?: number;
    /** The loan asset address to match against */
    loanToken?: string;
    /** Filter by a specific offer creator address */
    creator?: string;
    /** Filter by multiple statuses (comma-separated) */
    status?: OfferStatus[];
    /** Pagination cursor in base64url-encoded format */
    cursor?: string;
    /** Maximum number of offers to return. Defaults to 20. Maximum is 100. */
    limit?: number;
};
type RouterClientConfig = {
    readonly url: URL;
    readonly headers: Headers;
};
type Client = Compute<RouterClientConfig & {
    get: (parameters: GetParameters) => Promise<{
        cursor: string | null;
        offers: RouterOffer[];
    }>;
    match: (parameters: MatchParameters) => Promise<{
        cursor: string | null;
        offers: RouterOffer[];
    }>;
}>;
declare function connect(opts?: {
    url?: string;
    apiKey?: string;
}): Client;
declare namespace connect {
    type ErrorType = InvalidUrlError;
}
/**
 * Get offers from the router.
 * @returns The offers with pagination cursor.
 */
declare function get(config: RouterClientConfig, parameters: GetParameters): Promise<{
    cursor: string | null;
    offers: RouterOffer[];
}>;
declare namespace get {
    type ErrorType = GetApiErrorType;
}
/**
 * Match offers from the router.
 * @returns The matched offers with pagination cursor.
 */
declare function match(config: RouterClientConfig, parameters: MatchParameters): Promise<{
    cursor: string | null;
    offers: RouterOffer[];
}>;
declare namespace match {
    type ErrorType = GetApiErrorType;
}
type GetApiErrorType = HttpGetOffersFailedError | HttpUnauthorizedError | HttpForbiddenError | HttpRateLimitError;
declare class InvalidUrlError extends Errors.BaseError {
    name: string;
    constructor(url: string);
}
declare class HttpUnauthorizedError extends Errors.BaseError {
    name: string;
    constructor();
}
declare class HttpForbiddenError extends Errors.BaseError {
    name: string;
    constructor();
}
declare class HttpRateLimitError extends Errors.BaseError {
    name: string;
    constructor();
}
declare class HttpGetOffersFailedError extends Errors.BaseError {
    name: string;
    constructor(message: string, { details }?: {
        details?: string;
    });
}

type index_Client = Client;
type index_GetParameters = GetParameters;
type index_HttpForbiddenError = HttpForbiddenError;
declare const index_HttpForbiddenError: typeof HttpForbiddenError;
type index_HttpGetOffersFailedError = HttpGetOffersFailedError;
declare const index_HttpGetOffersFailedError: typeof HttpGetOffersFailedError;
type index_HttpRateLimitError = HttpRateLimitError;
declare const index_HttpRateLimitError: typeof HttpRateLimitError;
type index_HttpUnauthorizedError = HttpUnauthorizedError;
declare const index_HttpUnauthorizedError: typeof HttpUnauthorizedError;
type index_InvalidUrlError = InvalidUrlError;
declare const index_InvalidUrlError: typeof InvalidUrlError;
type index_MatchParameters = MatchParameters;
type index_RouterClientConfig = RouterClientConfig;
declare const index_connect: typeof connect;
declare const index_get: typeof get;
declare const index_match: typeof match;
declare namespace index {
  export { type index_Client as Client, type index_GetParameters as GetParameters, index_HttpForbiddenError as HttpForbiddenError, index_HttpGetOffersFailedError as HttpGetOffersFailedError, index_HttpRateLimitError as HttpRateLimitError, index_HttpUnauthorizedError as HttpUnauthorizedError, index_InvalidUrlError as InvalidUrlError, type index_MatchParameters as MatchParameters, type index_RouterClientConfig as RouterClientConfig, index_connect as connect, index_get as get, index_match as match };
}

declare const users: Account[];
declare const assetList: readonly ["USDC", "DAI"];
declare const mockAddress: (asset: (typeof assetList)[number]) => `0x${string}`;
declare const assetMethods: readonly ["balanceOf", "allowance"];
type AssetMethod = (typeof assetMethods)[number];
type MethodParameters = {
    balanceOf: {
        address: Address;
        value: bigint;
    };
    allowance: {
        owner: Address;
        spender: Address;
        value: bigint;
    };
};
type MockedAsset = {
    address: Address;
    set: (slot: Hex | AssetMethod, parameters: Hex | bigint | MethodParameters[AssetMethod]) => Promise<void>;
};
type Mocked = {
    name: string;
    publicClient: PublicClient;
} & Record<(typeof assetList)[number], MockedAsset>;
declare function mock(name: string): Promise<Mocked>;

type EVM_AssetMethod = AssetMethod;
type EVM_MethodParameters = MethodParameters;
type EVM_Mocked = Mocked;
type EVM_MockedAsset = MockedAsset;
declare const EVM_assetList: typeof assetList;
declare const EVM_assetMethods: typeof assetMethods;
declare const EVM_mock: typeof mock;
declare const EVM_mockAddress: typeof mockAddress;
declare const EVM_users: typeof users;
declare namespace EVM {
  export { type EVM_AssetMethod as AssetMethod, type EVM_MethodParameters as MethodParameters, type EVM_Mocked as Mocked, type EVM_MockedAsset as MockedAsset, EVM_assetList as assetList, EVM_assetMethods as assetMethods, EVM_mock as mock, EVM_mockAddress as mockAddress, EVM_users as users };
}

declare const LogLevelValues: readonly ["silent", "trace", "debug", "info", "warn", "error", "fatal"];
type LogLevel = (typeof LogLevelValues)[number];
type LogFn = {
    <T extends object>(obj: T, msg?: string, ...args: unknown[]): void;
    (obj: unknown, msg?: string, ...args: unknown[]): void;
    (msg: string, ...args: unknown[]): void;
};
type Logger = {
    trace: LogFn;
    debug: LogFn;
    info: LogFn;
    warn: LogFn;
    error: LogFn;
    fatal: LogFn;
};
declare function defaultLogger(): Logger;
declare function runWithLogger<T>(logger: Logger, fn: () => Promise<T>): Promise<T>;
declare function getLogger(): Logger;

type Logger$1_LogFn = LogFn;
type Logger$1_LogLevel = LogLevel;
declare const Logger$1_LogLevelValues: typeof LogLevelValues;
type Logger$1_Logger = Logger;
declare const Logger$1_defaultLogger: typeof defaultLogger;
declare const Logger$1_getLogger: typeof getLogger;
declare const Logger$1_runWithLogger: typeof runWithLogger;
declare namespace Logger$1 {
  export { type Logger$1_LogFn as LogFn, type Logger$1_LogLevel as LogLevel, Logger$1_LogLevelValues as LogLevelValues, type Logger$1_Logger as Logger, Logger$1_defaultLogger as defaultLogger, Logger$1_getLogger as getLogger, Logger$1_runWithLogger as runWithLogger };
}

declare const types: readonly ["offer_created", "offer_matched", "offer_validation"];
type Type = (typeof types)[number];
type EventPayload = {
    offer_created: {
        readonly offer: RouterOffer;
    };
    offer_matched: {
        readonly offer: RouterOffer;
    };
    offer_validation: {
        readonly offer: RouterOffer;
    };
};
type BaseEvent<T extends Type> = {
    readonly id: string;
    readonly type: T;
};
type RouterEvent = Compute<{
    [K in keyof EventPayload]: BaseEvent<K> & EventPayload[K];
}[keyof EventPayload]>;
/**
 * Builds a deterministic event id based on the event type.
 * For `offer_created` it returns `offer_created:${offer.hash.toLowerCase()}`.
 * For `offer_matched` it returns `offer_matched:${offer.hash.toLowerCase()}`.
 */
declare function buildId(event: Omit<RouterEvent, "id">): string;

type RouterEvent$1_RouterEvent = RouterEvent;
type RouterEvent$1_Type = Type;
declare const RouterEvent$1_buildId: typeof buildId;
declare const RouterEvent$1_types: typeof types;
declare namespace RouterEvent$1 {
  export { type RouterEvent$1_RouterEvent as RouterEvent, type RouterEvent$1_Type as Type, RouterEvent$1_buildId as buildId, RouterEvent$1_types as types };
}

/**
 * Splits an array into batches of a specified size.
 * @param array The array to split.
 * @param batchSize The size of each batch.
 * @returns An iterator that yields each batch.
 * @example
 * ```typescript
 * const array = [1, 2, 3, 4, 5];
 * for (const batch of batch(array, 2)) {
 *  console.log(batch);
 * }
 * // Output:
 * // [1, 2]
 * // [3, 4]
 * // [5]
 * ```
 */
declare function batch$1<T>(array: Array<T>, batchSize: number): Generator<T[], void, unknown>;

/**
 * Polls a function at a specified interval.
 * Inspired by https://github.com/wevm/viem/blob/845994d20275d08ff892018e237a4b599eeefb6a/src/utils/poll.ts
 */
declare function poll<data>(fn: ({ unpoll }: {
    unpoll: () => void;
}) => Promise<data | undefined>, { interval }: {
    interval: number;
}): () => boolean;

declare function wait(time: number): Promise<unknown>;

/**
 * A validation rule.
 */
type Rule<T, Name extends string = string, Ctx = void> = {
    kind: "single";
    name: Name;
    run: Single<T, Name, Ctx>;
} | {
    kind: "batch";
    name: Name;
    run: Batch<T, Name, Ctx>;
};
type RuleNames<Rules extends readonly {
    name: string;
}[]> = Rules[number]["name"];
/**
 * A single item validation rule.
 * @param item - The item to validate.
 * @param ctx - The context of the validation.
 * @returns The issue that was found. If the item is valid, this will be undefined.
 */
type Single<T, RuleName extends string, Ctx = void> = (item: T, ctx: Ctx) => Omit<Issue<T, RuleName>, "ruleName" | "item"> | undefined | Promise<Omit<Issue<T, RuleName>, "ruleName" | "item"> | undefined>;
/**
 * A batch item validation rule.
 * @param items - The items to validate.
 * @param ctx - The context of the validation.
 * @returns A map of the items to the issue that was found.
 */
type Batch<T, RuleName extends string, Ctx = void> = (items: T[], ctx: Ctx) => Map<number, Omit<Issue<T, RuleName>, "ruleName" | "item"> | undefined> | Promise<Map<number, Omit<Issue<T, RuleName>, "ruleName" | "item"> | undefined>>;
/**
 * Create a validation rule iterating over a single item at a time.
 * @param name - The name of the rule.
 * @param run - The function that validates the rule.
 * @returns The created rule.
 */
declare function single<Name extends string, T, Ctx = void>(name: Name, run: Single<T, Name, Ctx>): Rule<T, Name, Ctx>;
/**
 * Create a validation rule iterating over a batch of items at a time.
 * @param name - The name of the rule.
 * @param run - The function that validates the rule.
 * @returns The created rule.
 */
declare function batch<Name extends string, T, Ctx = void>(name: Name, run: Batch<T, Name, Ctx>): Rule<T, Name, Ctx>;
type MorphoContext = {
    publicClients: Partial<Record<ChainName, PublicClient>>;
};
declare function morpho(parameters: {
    whitelistedChains: Chain[];
}): (Rule<{
    readonly offering: Address;
    readonly assets: bigint;
    readonly rate: bigint;
    readonly maturity: number;
    readonly expiry: number;
    readonly nonce: bigint;
    readonly buy: boolean;
    readonly chainId: bigint;
    readonly loanToken: Address;
    readonly start: number;
    readonly collaterals: readonly {
        asset: Address;
        oracle: Address;
        lltv: bigint;
    }[];
    readonly callback: {
        readonly address: Address;
        readonly data: viem.Hex;
        readonly gasLimit: bigint;
    };
    readonly hash: viem.Hex;
    signature?: viem.Hex;
    createdAt?: number;
}, "chain_id", MorphoContext> | Rule<{
    readonly offering: Address;
    readonly assets: bigint;
    readonly rate: bigint;
    readonly maturity: number;
    readonly expiry: number;
    readonly nonce: bigint;
    readonly buy: boolean;
    readonly chainId: bigint;
    readonly loanToken: Address;
    readonly start: number;
    readonly collaterals: readonly {
        asset: Address;
        oracle: Address;
        lltv: bigint;
    }[];
    readonly callback: {
        readonly address: Address;
        readonly data: viem.Hex;
        readonly gasLimit: bigint;
    };
    readonly hash: viem.Hex;
    signature?: viem.Hex;
    createdAt?: number;
}, "loan_token", MorphoContext> | Rule<{
    readonly offering: Address;
    readonly assets: bigint;
    readonly rate: bigint;
    readonly maturity: number;
    readonly expiry: number;
    readonly nonce: bigint;
    readonly buy: boolean;
    readonly chainId: bigint;
    readonly loanToken: Address;
    readonly start: number;
    readonly collaterals: readonly {
        asset: Address;
        oracle: Address;
        lltv: bigint;
    }[];
    readonly callback: {
        readonly address: Address;
        readonly data: viem.Hex;
        readonly gasLimit: bigint;
    };
    readonly hash: viem.Hex;
    signature?: viem.Hex;
    createdAt?: number;
}, "expiry", MorphoContext> | Rule<{
    readonly offering: Address;
    readonly assets: bigint;
    readonly rate: bigint;
    readonly maturity: number;
    readonly expiry: number;
    readonly nonce: bigint;
    readonly buy: boolean;
    readonly chainId: bigint;
    readonly loanToken: Address;
    readonly start: number;
    readonly collaterals: readonly {
        asset: Address;
        oracle: Address;
        lltv: bigint;
    }[];
    readonly callback: {
        readonly address: Address;
        readonly data: viem.Hex;
        readonly gasLimit: bigint;
    };
    readonly hash: viem.Hex;
    signature?: viem.Hex;
    createdAt?: number;
}, "empty_callback", MorphoContext> | Rule<{
    readonly offering: Address;
    readonly assets: bigint;
    readonly rate: bigint;
    readonly maturity: number;
    readonly expiry: number;
    readonly nonce: bigint;
    readonly buy: boolean;
    readonly chainId: bigint;
    readonly loanToken: Address;
    readonly start: number;
    readonly collaterals: readonly {
        asset: Address;
        oracle: Address;
        lltv: bigint;
    }[];
    readonly callback: {
        readonly address: Address;
        readonly data: viem.Hex;
        readonly gasLimit: bigint;
    };
    readonly hash: viem.Hex;
    signature?: viem.Hex;
    createdAt?: number;
}, "sell_offers_empty_callback", MorphoContext> | Rule<{
    readonly offering: Address;
    readonly assets: bigint;
    readonly rate: bigint;
    readonly maturity: number;
    readonly expiry: number;
    readonly nonce: bigint;
    readonly buy: boolean;
    readonly chainId: bigint;
    readonly loanToken: Address;
    readonly start: number;
    readonly collaterals: readonly {
        asset: Address;
        oracle: Address;
        lltv: bigint;
    }[];
    readonly callback: {
        readonly address: Address;
        readonly data: viem.Hex;
        readonly gasLimit: bigint;
    };
    readonly hash: viem.Hex;
    signature?: viem.Hex;
    createdAt?: number;
}, "buy_offers_empty_callback", MorphoContext>)[];

type ValidationRule_Batch<T, RuleName extends string, Ctx = void> = Batch<T, RuleName, Ctx>;
type ValidationRule_MorphoContext = MorphoContext;
type ValidationRule_Rule<T, Name extends string = string, Ctx = void> = Rule<T, Name, Ctx>;
type ValidationRule_RuleNames<Rules extends readonly {
    name: string;
}[]> = RuleNames<Rules>;
type ValidationRule_Single<T, RuleName extends string, Ctx = void> = Single<T, RuleName, Ctx>;
declare const ValidationRule_batch: typeof batch;
declare const ValidationRule_morpho: typeof morpho;
declare const ValidationRule_single: typeof single;
declare namespace ValidationRule {
  export { type ValidationRule_Batch as Batch, type ValidationRule_MorphoContext as MorphoContext, type ValidationRule_Rule as Rule, type ValidationRule_RuleNames as RuleNames, type ValidationRule_Single as Single, ValidationRule_batch as batch, ValidationRule_morpho as morpho, ValidationRule_single as single };
}

/**
 * A validation issue.
 */
type Issue<T, RuleName extends string = string> = {
    /** The name of the rule that caused the issue. */
    ruleName: RuleName;
    /** The message of the issue. */
    message: string;
    /** The item that was not valid. */
    item: T;
};
/**
 * The result of a validation.
 */
type Result<T, RuleName extends string = string> = {
    /** The items that were valid. */
    valid: T[];
    /** The reports of the failed validations. */
    issues: Issue<T, RuleName>[];
};
declare function run<T, Name extends string, Rules extends readonly Rule<T, Name, void>[]>(parameters: {
    items: T[];
    rules: Rules;
    chunkSize?: number;
}): Promise<Result<T, RuleNames<Rules>>>;
declare function run<T, Ctx, Name extends string, Rules extends readonly Rule<T, Name, Ctx>[]>(parameters: {
    items: T[];
    rules: Rules;
    ctx: Ctx;
    chunkSize?: number;
}): Promise<Result<T, RuleNames<Rules>>>;

type Validation_Issue<T, RuleName extends string = string> = Issue<T, RuleName>;
type Validation_Result<T, RuleName extends string = string> = Result<T, RuleName>;
declare const Validation_run: typeof run;
declare namespace Validation {
  export { type Validation_Issue as Issue, type Validation_Result as Result, Validation_run as run };
}

export { Chain$1 as Chain, type Compute, EVM, Logger$1 as Logger, index as Router, RouterEvent$1 as RouterEvent, RouterOffer$1 as RouterOffer, Validation, ValidationRule, batch$1 as batch, poll, wait };
