import { assert } from '@0x/assert'; import { APIOrder } from '@0x/connect'; import { AssetPairsItem, SignedOrder } from '@0x/types'; import { BaseOrderProvider } from './order_provider/base_order_provider'; import { CustomOrderProvider } from './order_provider/custom_order_provider'; import { MeshOrderProvider } from './order_provider/mesh_order_provider'; import { SRAPollingOrderProvider } from './order_provider/sra_polling_order_provider'; import { SRAWebsocketOrderProvider } from './order_provider/sra_websocket_order_provider'; import { OrderStore } from './order_store'; import { AcceptedRejectedOrders, MeshOrderProviderOpts, SRAPollingOrderProviderOpts, SRAWebsocketOrderProviderOpts, } from './types'; export class Orderbook { private readonly _orderProvider: BaseOrderProvider; private readonly _orderStore: OrderStore; /** * Creates an Orderbook with the provided orders. This provider simply stores the * orders and allows querying. No validation or subscriptions occur. * @param orders the set of SignedOrders */ public static getOrderbookForProvidedOrders(orders: SignedOrder[]): Orderbook { const orderStore = new OrderStore(); return new Orderbook(new CustomOrderProvider(orders, orderStore), orderStore); } /** * Creates an Orderbook with the SRA Websocket Provider. This Provider fetches orders via * the SRA http endpoint and then subscribes to the asset pair for future updates. * @param opts the `SRAWebsocketOrderProviderOpts` */ public static getOrderbookForWebsocketProvider(opts: SRAWebsocketOrderProviderOpts): Orderbook { const orderStore = new OrderStore(); return new Orderbook(new SRAWebsocketOrderProvider(opts, orderStore), orderStore); } /** * Creates an Orderbook with SRA Polling Provider. This Provider simply polls every interval. * @param opts the `SRAPollingOrderProviderOpts` */ public static getOrderbookForPollingProvider(opts: SRAPollingOrderProviderOpts): Orderbook { const orderStore = new OrderStore(); return new Orderbook(new SRAPollingOrderProvider(opts, orderStore), orderStore); } /** * Creates an Orderbook with a Mesh Order Provider. This Provider fetches ALL orders * and subscribes to updates on ALL orders. * @param opts the `MeshOrderProviderOpts` */ public static getOrderbookForMeshProvider(opts: MeshOrderProviderOpts): Orderbook { const orderStore = new OrderStore(); return new Orderbook(new MeshOrderProvider(opts, orderStore), orderStore); } /** * Creates an Orderbook with the order provider. All order updates are stored * in the `OrderStore`. * @param orderProvider the order provider, e.g SRAWebbsocketOrderProvider * @param orderStore the order store where orders are added and deleted */ constructor(orderProvider: BaseOrderProvider, orderStore: OrderStore) { this._orderProvider = orderProvider; this._orderStore = orderStore; } /** * Returns all orders where the order.makerAssetData == makerAssetData and * order.takerAssetData == takerAssetData. This pair is then subscribed to * and all future updates will be stored. The first request * to `getOrdersAsync` might fetch the orders from the Order Provider and create a subscription. * Subsequent requests will be quick and up to date and synced with the Order Provider state. * @param makerAssetData the maker asset data * @param takerAssetData the taker asset data */ public async getOrdersAsync(makerAssetData: string, takerAssetData: string): Promise { assert.isString('makerAssetData', makerAssetData); assert.isString('takerAssetData', takerAssetData); const assetPairKey = OrderStore.getKeyForAssetPair(makerAssetData, takerAssetData); if (!this._orderStore.has(assetPairKey)) { await this._orderProvider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); } const orders = this._orderStore.values(assetPairKey); return orders.filter( o => o.order.makerAssetData === makerAssetData && o.order.takerAssetData === takerAssetData, ); } /** * Returns all of the Available Asset Pairs for the provided Order Provider. */ public async getAvailableAssetDatasAsync(): Promise { return this._orderProvider.getAvailableAssetDatasAsync(); } /** * Adds the orders to the Order Provider. All accepted orders will be returned * and rejected orders will be returned with an message indicating a reason for its rejection * @param orders The set of Orders to add to the Order Provider */ public async addOrdersAsync(orders: SignedOrder[]): Promise { return this._orderProvider.addOrdersAsync(orders); } /** * Destroys any subscriptions or connections. */ public async destroyAsync(): Promise { return this._orderProvider.destroyAsync(); } }