/// <reference types="bn.js" />
/**
 * DLOB — Decentralized Limit Order Book.
 *
 * Maintains an in-memory order book built from on-chain `User` accounts.
 * Used by keeper bots to identify the best maker orders to match against taker fills.
 *
 * Key types:
 *   {@link DLOBNode}        — a single order node with price/size/user info (DLOBNode.ts)
 *   {@link DLOBSubscriber}  — subscribes to on-chain accounts and keeps the DLOB live (DLOBSubscriber.ts)
 *   {@link NodeList}        — sorted linked list of DLOBNodes per side/market (NodeList.ts)
 *   `orderBookLevels.ts`    — aggregated L2/L3 book level construction for quoting
 */
import { NodeList } from './NodeList';
import { BN } from '../isomorphic/anchor';
import { DLOBNode, DLOBNodeType, TriggerOrderNode } from './DLOBNode';
import { DriftClient } from '../driftClient';
import { MarketType, MarketTypeStr, Order, PerpMarketAccount, PositionDirection, SpotMarketAccount, StateAccount } from '../types';
import { MMOraclePriceData, OraclePriceData } from '../oracles/types';
import { ProtectMakerParamsMap } from './types';
import { SlotSubscriber } from '../slot/SlotSubscriber';
import { UserMap } from '../userMap/userMap';
import { PublicKey } from '@solana/web3.js';
import { L2OrderBook, L2OrderBookGenerator, L3OrderBook } from './orderBookLevels';
export type DLOBOrder = {
    user: PublicKey;
    order: Order;
};
export type DLOBOrders = DLOBOrder[];
export type MarketNodeLists = {
    restingLimit: {
        ask: NodeList<'restingLimit'>;
        bid: NodeList<'restingLimit'>;
    };
    floatingLimit: {
        ask: NodeList<'floatingLimit'>;
        bid: NodeList<'floatingLimit'>;
    };
    protectedFloatingLimit: {
        ask: NodeList<'protectedFloatingLimit'>;
        bid: NodeList<'protectedFloatingLimit'>;
    };
    takingLimit: {
        ask: NodeList<'takingLimit'>;
        bid: NodeList<'takingLimit'>;
    };
    market: {
        ask: NodeList<'market'>;
        bid: NodeList<'market'>;
    };
    trigger: {
        above: NodeList<'trigger'>;
        below: NodeList<'trigger'>;
    };
    signedMsg: {
        ask: NodeList<'signedMsg'>;
        bid: NodeList<'signedMsg'>;
    };
};
type OrderBookCallback = () => void;
/**
 *  Receives a DLOBNode and is expected to return true if the node should
 *  be taken into account when generating, or false otherwise.
 *
 * Currently used in functions that rely on getBestNode
 */
export type DLOBFilterFcn = (node: DLOBNode) => boolean;
export type NodeToFill = {
    node: DLOBNode;
    makerNodes: DLOBNode[];
};
export type NodeToTrigger = {
    node: TriggerOrderNode;
};
export declare class DLOB {
    openOrders: Map<MarketTypeStr, Set<string>>;
    orderLists: Map<MarketTypeStr, Map<number, MarketNodeLists>>;
    maxSlotForRestingLimitOrders: number;
    initialized: boolean;
    protectedMakerParamsMap: ProtectMakerParamsMap;
    constructor(protectedMakerParamsMap?: ProtectMakerParamsMap);
    private init;
    clear(): void;
    /**
     * initializes a new DLOB instance
     *
     * @returns a promise that resolves when the DLOB is initialized
     */
    initFromUserMap(userMap: UserMap, slot: number): Promise<boolean>;
    insertOrder(order: Order, userAccount: string, slot: number, isUserProtectedMaker: boolean, baseAssetAmount: BN, onInsert?: OrderBookCallback): void;
    insertSignedMsgOrder(order: Order, userAccount: string, isUserProtectedMaker: boolean, baseAssetAmount?: BN, onInsert?: OrderBookCallback): void;
    addOrderList(marketType: MarketTypeStr, marketIndex: number): void;
    delete(order: Order, userAccount: PublicKey, slot: number, isUserProtectedMaker: boolean, onDelete?: OrderBookCallback): void;
    getListForOnChainOrder(order: Order, slot: number, isProtectedMaker: boolean): NodeList<any> | undefined;
    updateRestingLimitOrders(slot: number): void;
    updateRestingLimitOrdersForMarketType(slot: number, marketTypeStr: MarketTypeStr): void;
    getOrder(orderId: number, userAccount: PublicKey): Order | undefined;
    findNodesToFill<T extends MarketType>(marketIndex: number, fallbackBid: BN | undefined, fallbackAsk: BN | undefined, slot: number, ts: number, marketType: T, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData, stateAccount: StateAccount, marketAccount: T extends {
        spot: unknown;
    } ? SpotMarketAccount : PerpMarketAccount): NodeToFill[];
    getMakerRebate(marketType: MarketType, stateAccount: StateAccount, marketAccount: PerpMarketAccount | SpotMarketAccount): {
        makerRebateNumerator: number;
        makerRebateDenominator: number;
    };
    mergeNodesToFill(restingLimitOrderNodesToFill: NodeToFill[], takingOrderNodesToFill: NodeToFill[]): NodeToFill[];
    findRestingLimitOrderNodesToFill<T extends MarketType>(marketIndex: number, slot: number, marketType: T, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData, isAmmPaused: boolean, stateAccount: StateAccount, marketAccount: T extends {
        spot: unknown;
    } ? SpotMarketAccount : PerpMarketAccount, makerRebateNumerator: number, makerRebateDenominator: number, fallbackAsk: BN | undefined, fallbackBid: BN | undefined): NodeToFill[];
    findTakingNodesToFill<T extends MarketType>(marketIndex: number, slot: number, marketType: T, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData, isAmmPaused: boolean, state: StateAccount, marketAccount: T extends {
        spot: unknown;
    } ? SpotMarketAccount : PerpMarketAccount, fallbackAsk: BN | undefined, fallbackBid?: BN | undefined): NodeToFill[];
    findTakingNodesCrossingMakerNodes<T extends MarketType>(marketIndex: number, slot: number, marketType: T, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData, takerNodeGenerator: Generator<DLOBNode>, makerNodeGeneratorFn: (marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData) => Generator<DLOBNode>, doesCross: (takerPrice: BN | undefined, makerPrice: BN) => boolean): NodeToFill[];
    findNodesCrossingFallbackLiquidity<T extends MarketType>(marketType: T, slot: number, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData, nodeGenerator: Generator<DLOBNode>, doesCross: (nodePrice: BN | undefined) => boolean, state: StateAccount, marketAccount: T extends {
        spot: unknown;
    } ? SpotMarketAccount : PerpMarketAccount): NodeToFill[];
    findExpiredNodesToFill(marketIndex: number, ts: number, marketType: MarketType, slot?: BN): NodeToFill[];
    findUnfillableReduceOnlyOrdersToCancel(marketIndex: number, marketType: MarketType, stepSize: BN): NodeToFill[];
    getTakingBids<T extends MarketType>(marketIndex: number, marketType: T, slot: number, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData, filterFcn?: DLOBFilterFcn): Generator<DLOBNode>;
    getTakingAsks<T extends MarketType>(marketIndex: number, marketType: T, slot: number, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData, filterFcn?: DLOBFilterFcn): Generator<DLOBNode>;
    protected signedMsgGenerator(signedMsgOrderList: NodeList<'signedMsg'>, filter: (x: DLOBNode) => boolean): Generator<DLOBNode>;
    protected getBestNode<T extends MarketTypeStr>(generatorList: Array<Generator<DLOBNode>>, oraclePriceData: T extends 'spot' ? OraclePriceData : MMOraclePriceData, slot: number, compareFcn: (bestDLOBNode: DLOBNode, currentDLOBNode: DLOBNode, slot: number, oraclePriceData: T extends 'spot' ? OraclePriceData : MMOraclePriceData) => boolean, filterFcn?: DLOBFilterFcn): Generator<DLOBNode>;
    getRestingLimitAsks<T extends MarketType>(marketIndex: number, slot: number, marketType: T, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData, filterFcn?: DLOBFilterFcn): Generator<DLOBNode>;
    getRestingLimitBids<T extends MarketType>(marketIndex: number, slot: number, marketType: T, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData, filterFcn?: DLOBFilterFcn): Generator<DLOBNode>;
    /**
     * This will look at both the taking and resting limit asks
     * @param marketIndex
     * @param fallbackAsk
     * @param slot
     * @param marketType
     * @param oraclePriceData
     * @param filterFcn
     */
    getAsks<T extends MarketType>(marketIndex: number, _fallbackAsk: BN | undefined, slot: number, marketType: T, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData, filterFcn?: DLOBFilterFcn): Generator<DLOBNode>;
    /**
     * This will look at both the taking and resting limit bids
     * @param marketIndex
     * @param fallbackBid
     * @param slot
     * @param marketType
     * @param oraclePriceData
     * @param filterFcn
     */
    getBids<T extends MarketType>(marketIndex: number, _fallbackBid: BN | undefined, slot: number, marketType: T, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData, filterFcn?: DLOBFilterFcn): Generator<DLOBNode>;
    findCrossingRestingLimitOrders<T extends MarketType>(marketIndex: number, slot: number, marketType: T, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData): NodeToFill[];
    determineMakerAndTaker(askNode: DLOBNode, bidNode: DLOBNode): {
        takerNode: DLOBNode;
        makerNode: DLOBNode;
    } | undefined;
    getBestAsk<T extends MarketType>(marketIndex: number, slot: number, marketType: T, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData): BN | undefined;
    getBestBid<T extends MarketType>(marketIndex: number, slot: number, marketType: T, oraclePriceData: T extends {
        spot: unknown;
    } ? OraclePriceData : MMOraclePriceData): BN | undefined;
    getStopLosses(marketIndex: number, marketType: MarketType, direction: PositionDirection): Generator<DLOBNode>;
    getStopLossMarkets(marketIndex: number, marketType: MarketType, direction: PositionDirection): Generator<DLOBNode>;
    getStopLossLimits(marketIndex: number, marketType: MarketType, direction: PositionDirection): Generator<DLOBNode>;
    getTakeProfits(marketIndex: number, marketType: MarketType, direction: PositionDirection): Generator<DLOBNode>;
    getTakeProfitMarkets(marketIndex: number, marketType: MarketType, direction: PositionDirection): Generator<DLOBNode>;
    getTakeProfitLimits(marketIndex: number, marketType: MarketType, direction: PositionDirection): Generator<DLOBNode>;
    findNodesToTrigger(marketIndex: number, slot: number, triggerPrice: BN, marketType: MarketType, stateAccount: StateAccount): NodeToTrigger[];
    printTop(driftClient: DriftClient, slotSubscriber: SlotSubscriber, marketIndex: number, marketType: MarketType): void;
    getDLOBOrders(): DLOBOrders;
    getNodeLists(): Generator<NodeList<DLOBNodeType>>;
    /**
     * Get an L2 view of the order book for a given market.
     *
     * @param marketIndex
     * @param marketType
     * @param slot
     * @param oraclePriceData
     * @param depth how many levels of the order book to return
     * @param fallbackL2Generators L2 generators for fallback liquidity e.g. vAMM {@link getVammL2Generator}, openbook {@link SerumSubscriber}
     */
    getL2<T extends MarketType>({ marketIndex, marketType, slot, oraclePriceData, depth, fallbackL2Generators, }: {
        marketIndex: number;
        marketType: T;
        slot: number;
        oraclePriceData: T extends {
            spot: unknown;
        } ? OraclePriceData : MMOraclePriceData;
        depth: number;
        fallbackL2Generators?: L2OrderBookGenerator[];
    }): L2OrderBook;
    /**
     * Get an L3 view of the order book for a given market. Does not include fallback liquidity sources
     *
     * @param marketIndex
     * @param marketType
     * @param slot
     * @param oraclePriceData
     */
    getL3<T extends MarketType>({ marketIndex, marketType, slot, oraclePriceData, }: {
        marketIndex: number;
        marketType: T;
        slot: number;
        oraclePriceData: T extends {
            spot: unknown;
        } ? OraclePriceData : MMOraclePriceData;
    }): L3OrderBook;
    private estimateFillExactBaseAmountInForSide;
    /**
     *
     * @param param.marketIndex the index of the market
     * @param param.marketType the type of the market
     * @param param.baseAmount the base amount in to estimate
     * @param param.orderDirection the direction of the trade
     * @param param.slot current slot for estimating dlob node price
     * @param param.oraclePriceData the oracle price data
     * @returns the estimated quote amount filled: QUOTE_PRECISION
     */
    estimateFillWithExactBaseAmount<T extends MarketType>({ marketIndex, marketType, baseAmount, orderDirection, slot, oraclePriceData, }: {
        marketIndex: number;
        marketType: T;
        baseAmount: BN;
        orderDirection: PositionDirection;
        slot: number;
        oraclePriceData: T extends {
            spot: unknown;
        } ? OraclePriceData : MMOraclePriceData;
    }): BN;
    getBestMakers<T extends MarketType>({ marketIndex, marketType, direction, slot, oraclePriceData, numMakers, }: {
        marketIndex: number;
        marketType: T;
        direction: PositionDirection;
        slot: number;
        oraclePriceData: T extends {
            spot: unknown;
        } ? OraclePriceData : MMOraclePriceData;
        numMakers: number;
    }): PublicKey[];
}
export {};
//# sourceMappingURL=DLOB.d.ts.map