UNPKG

xud

Version:
226 lines (225 loc) 12 kB
/// <reference types="node" /> import { EventEmitter } from 'events'; import { Models } from '../db/DB'; import { CurrencyCreationAttributes, CurrencyInstance, PairInstance } from '../db/types'; import Logger from '../Logger'; import Pool from '../p2p/Pool'; import Swaps from '../swaps/Swaps'; import { SwapSuccess } from '../swaps/types'; import TradingPair from './TradingPair'; import { OrderBookThresholds, OrderPortion, OwnLimitOrder, OwnMarketOrder, OwnOrder, Pair, PeerOrder, PlaceOrderEvent, PlaceOrderResult } from './types'; interface OrderBook { /** Adds a listener to be called when a remote order was added. */ on(event: 'peerOrder.incoming', listener: (order: PeerOrder) => void): this; /** Adds a listener to be called when all or part of a remote order was invalidated and removed */ on(event: 'peerOrder.invalidation', listener: (order: OrderPortion) => void): this; /** Adds a listener to be called when all or part of a remote order was filled by an own order and removed */ on(event: 'peerOrder.filled', listener: (order: OrderPortion) => void): this; /** Adds a listener to be called when all or part of a local order was swapped after being filled and executed remotely */ on(event: 'ownOrder.swapped', listener: (order: OrderPortion) => void): this; /** Adds a listener to be called when all or part of a local order was filled by an own order and removed */ on(event: 'ownOrder.filled', listener: (order: OwnOrder) => void): this; /** Adds a listener to be called when a local order was added */ on(event: 'ownOrder.added', listener: (order: OwnOrder) => void): this; /** Adds a listener to be called when a local order was removed either manually or due to a swap initiated by a peer */ on(event: 'ownOrder.removed', listener: (order: OwnOrder) => void): this; /** Notifies listeners that a remote order was added */ emit(event: 'peerOrder.incoming', order: PeerOrder): boolean; /** Notifies listeners that all or part of a remote order was invalidated and removed */ emit(event: 'peerOrder.invalidation', order: OrderPortion): boolean; /** Notifies listeners that all or part of a remote order was filled by an own order and removed */ emit(event: 'peerOrder.filled', order: OrderPortion): boolean; /** Notifies listeners that all or part of a local order was swapped after being filled and executed remotely */ emit(event: 'ownOrder.swapped', order: OrderPortion): boolean; /** Notifies listeners that all or part of a local order was filled by an own order and removed */ emit(event: 'ownOrder.filled', order: OwnOrder): boolean; /** Notifies listeners that a local order was added */ emit(event: 'ownOrder.added', order: OwnOrder): boolean; /** Notifies listeners that a local order was removed either manually or due to a swap initiated by a peer */ emit(event: 'ownOrder.removed', order: OwnOrder): boolean; } /** * Represents an order book containing all orders for all active trading pairs. This encompasses * all orders tracked locally and is the primary interface with which other modules interact with * the order book. */ declare class OrderBook extends EventEmitter { /** A map between active trading pair ids and trading pair instances. */ tradingPairs: Map<string, TradingPair>; nomatching: boolean; /** A map between own orders local id and their global id. */ private localIdMap; /** A map of supported currency tickers to currency instances. */ private currencyInstances; /** A map of supported trading pair tickers and pair database instances. */ private pairInstances; private repository; private thresholds; private logger; private nosanityswaps; private nobalancechecks; private strict; private pool; private swaps; /** Max time for placeOrder iterations (due to swaps failures retries). */ private static readonly MAX_PLACEORDER_ITERATIONS_TIME; /** Max time for sanity swaps to succeed. */ private static readonly MAX_SANITY_SWAP_TIME; /** Gets an array of supported pair ids. */ get pairIds(): string[]; get currencies(): Map<string, CurrencyInstance>; constructor({ logger, models, thresholds, pool, swaps, nosanityswaps, nobalancechecks, nomatching, strict }: { logger: Logger; models: Models; thresholds: OrderBookThresholds; pool: Pool; swaps: Swaps; nosanityswaps: boolean; nobalancechecks: boolean; nomatching?: boolean; strict?: boolean; }); private static createOutgoingOrder; private checkThresholdCompliance; /** * Checks that a currency advertised by a peer is known to us, has a swap client identifier, * and that their token identifier matches ours. */ private isPeerCurrencySupported; private bindPool; private bindSwaps; /** Loads the supported pairs and currencies from the database. */ init: () => Promise<void>; /** * Gets all trades or a limited number of trades from the database. */ getTrades: (limit?: number | undefined) => Promise<import("../db/types").TradeInstance[]>; /** * Get lists of buy and sell orders of peers. */ getPeersOrders: (pairId: string) => import("./TradingPair").OrderSidesArrays<PeerOrder>; /** * Get lists of this node's own buy and sell orders. */ getOwnOrders: (pairId: string) => import("./TradingPair").OrderSidesArrays<OwnOrder>; /** Get the trading pair instance for a given pairId, or throw an error if none exists. */ private getTradingPair; /** * Gets an own order by order id and pair id. * @returns The order matching parameters, or undefined if no order could be found. */ getOwnOrder: (orderId: string, pairId: string) => OwnOrder; private tryGetOwnOrder; getPeerOrder: (orderId: string, pairId: string, peerPubKey: string) => PeerOrder; addPair: (pair: Pair) => Promise<PairInstance>; private addTradingPair; addCurrency: (currency: CurrencyCreationAttributes) => Promise<void>; removeCurrency: (currencyId: string) => Promise<void>; removePair: (pairId: string) => Promise<void>; placeLimitOrder: ({ order, immediateOrCancel, replaceOrderId, onUpdate }: { order: OwnLimitOrder; immediateOrCancel?: boolean | undefined; replaceOrderId?: string | undefined; onUpdate?: ((e: PlaceOrderEvent) => void) | undefined; }) => Promise<PlaceOrderResult>; placeMarketOrder: ({ order, onUpdate }: { order: OwnMarketOrder; onUpdate?: ((e: PlaceOrderEvent) => void) | undefined; }) => Promise<PlaceOrderResult>; /** * Places an order in the order book. This method first attempts to match the order with existing * orders by price and initiate swaps for any matches with peer orders. It can be called recursively * for any portions of the order that fail swaps. * @param order the order to place * @param discardRemaining whether to discard any unmatched portion of the order, if `false` the * unmatched portion will enter the order book. * @param onUpdate a callback for when there are updates to the matching and order placement * routine including internal matches, successful swaps, failed swaps, and remaining orders * @param maxTime the deadline in epoch milliseconds for this method to end recursive calls */ private placeOrder; /** * Executes a swap between maker and taker orders. Emits the `peerOrder.filled` event if the swap succeeds. * @returns A promise that resolves to a [[SwapSuccess]] once the swap is completed, throws a [[SwapFailureReason]] if it fails */ executeSwap: (maker: PeerOrder, taker: OwnOrder) => Promise<SwapSuccess>; /** * Adds an own order to the order book and broadcasts it to peers. * Optionally removes/replaces an existing order. * @returns false if it's a duplicated order or with an invalid pair id, otherwise true */ private addOwnOrder; private persistTrade; /** * Adds an incoming peer order to the local order book. It timestamps the order based on when it * enters the order book and also records its initial quantity upon being received. * @returns `false` if it's a duplicated order or with an invalid pair id, otherwise true */ private addPeerOrder; getOwnOrderByLocalId: (localId: string) => OwnOrder; removeOwnOrders: () => { removedOrderLocalIds: string[]; onHoldOrderLocalIds: string[]; }; /** * Removes all or part of an order from the order book by its local id. Throws an error if the * specified pairId is not supported or if the order to cancel could not be found. * @param allowAsyncRemoval whether to allow an eventual async removal of the order in case * some quantity of the order is on hold and cannot be immediately removed. If false, while some quantity of * the order is on hold, an error will be thrown. * @param quantityToRemove the quantity to remove from the order, if undefined then the entire * order is removed. * @returns an object summarizing the result of the order removal, including any quantity that * was on hold and could not be immediately removed, the total quantity removed, and the quantity * remaining on the order. */ removeOwnOrderByLocalId: (localId: string, allowAsyncRemoval?: boolean | undefined, quantityToRemove?: number | undefined) => { removedQuantity: number; onHoldQuantity: number; pairId: string; remainingQuantity: number; }; private addOrderHold; private removeOrderHold; /** * Removes all or part of an own order from the order book and broadcasts an order invalidation packet. * @param quantityToRemove the quantity to remove from the order, if undefined then the full order is removed * @param takerPubKey the node pub key of the taker who filled this order, if applicable * @returns the removed portion of the order */ private removeOwnOrder; /** * Removes all or part of a peer order from the order book and emits the `peerOrder.invalidation` event. * @param quantityToRemove the quantity to remove from the order, if undefined then the full order is removed */ removePeerOrder: (orderId: string, pairId: string, peerPubKey?: string | undefined, quantityToRemove?: number | undefined) => { order: PeerOrder; fullyRemoved: boolean; }; private removePeerOrders; private removePeerPair; private checkPeerCurrencies; /** * Verifies the advertised trading pairs of a peer. Checks that the peer has advertised * lnd pub keys for both the base and quote currencies for each pair, and optionally attempts a * "sanity swap" for each currency which is a 1 satoshi for 1 satoshi swap of a given currency * that demonstrates that we can both accept and receive payments for this peer. * @param pairIds the list of trading pair ids to verify */ private verifyPeerPairs; /** * Send local orders to a given peer in an [[OrdersPacket]. * @param reqId the request id of a [[GetOrdersPacket]] packet that this method is responding to * @param pairIds a list of trading pair ids, only orders belonging to one of these pairs will be sent */ private sendOrders; stampOwnOrder: (order: OwnLimitOrder, replaceOrderId?: string | undefined) => OwnOrder; private handleOrderInvalidation; /** * Handles a request from a peer to create a swap deal. Checks if the order for the requested swap * is available and if a route exists to determine if the request should be accepted or rejected. * Responds to the peer with a swap response packet containing either an accepted quantity or rejection reason. */ private handleSwapRequest; } export default OrderBook;