From c324fe204efd3b94a7f142317a762a9d299f3de4 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Tue, 10 Dec 2019 20:19:25 -0800 Subject: [PATCH] Make OrderStore async for use in db adapter CHANGELOGS --- packages/asset-swapper/CHANGELOG.json | 9 ++++++++ .../src/utils/protocol_fee_utils.ts | 6 ++++- packages/orderbook/CHANGELOG.json | 9 ++++++++ .../src/order_provider/base_order_provider.ts | 4 +--- .../order_provider/custom_order_provider.ts | 22 ++++++++++++------- .../src/order_provider/mesh_order_provider.ts | 6 ++--- .../sra_polling_order_provider.ts | 2 +- .../sra_websocket_order_provider.ts | 4 ++-- packages/orderbook/src/order_store.ts | 16 +++++++------- packages/orderbook/src/orderbook.ts | 4 ++-- .../mesh_order_provider.test.ts | 8 +++---- .../sra_polling_order_provider.test.ts | 4 ++-- .../sra_websocket_order_provider.test.ts | 5 +++-- 13 files changed, 63 insertions(+), 36 deletions(-) diff --git a/packages/asset-swapper/CHANGELOG.json b/packages/asset-swapper/CHANGELOG.json index 245ae1967e..089b70fed7 100644 --- a/packages/asset-swapper/CHANGELOG.json +++ b/packages/asset-swapper/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "3.0.2", + "changes": [ + { + "note": "Fix gasPrice from `ethgasstation` to be in WEI instead of GWEI", + "pr": 2393 + } + ] + }, { "timestamp": 1575931811, "version": "3.0.1", diff --git a/packages/asset-swapper/src/utils/protocol_fee_utils.ts b/packages/asset-swapper/src/utils/protocol_fee_utils.ts index 5207284054..cd857301df 100644 --- a/packages/asset-swapper/src/utils/protocol_fee_utils.ts +++ b/packages/asset-swapper/src/utils/protocol_fee_utils.ts @@ -18,7 +18,11 @@ export class ProtocolFeeUtils { const gasInfo = await res.json(); // Eth Gas Station result is gwei * 10 // tslint:disable-next-line:custom-no-magic-numbers - return new BigNumber(gasInfo.fast / 10); + const BASE_TEN = 10; + const gasPriceGwei = new BigNumber(gasInfo.fast / BASE_TEN); + const unit = new BigNumber(BASE_TEN).pow(BASE_TEN); + const gasPriceWei = unit.times(gasPriceGwei); + return gasPriceWei; } catch (e) { throw new Error(SwapQuoterError.NoGasPriceProvidedOrEstimated); } diff --git a/packages/orderbook/CHANGELOG.json b/packages/orderbook/CHANGELOG.json index bfc454d707..32692c533b 100644 --- a/packages/orderbook/CHANGELOG.json +++ b/packages/orderbook/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "2.0.0", + "changes": [ + { + "note": "Change OrderStore functions to be async, allowing for Database adapters", + "pr": 2393 + } + ] + }, { "timestamp": 1575931811, "version": "1.0.1", diff --git a/packages/orderbook/src/order_provider/base_order_provider.ts b/packages/orderbook/src/order_provider/base_order_provider.ts index e831d0fd05..ffa596be8c 100644 --- a/packages/orderbook/src/order_provider/base_order_provider.ts +++ b/packages/orderbook/src/order_provider/base_order_provider.ts @@ -27,8 +27,6 @@ export abstract class BaseOrderProvider { public abstract async addOrdersAsync(orders: SignedOrder[]): Promise; protected async _updateStoreAsync(addedRemoved: AddedRemovedOrders): Promise { - const orderSet = this._orderStore.getOrderSetForAssetPair(addedRemoved.assetPairKey); - await orderSet.addManyAsync(addedRemoved.added); - await orderSet.deleteManyAsync(addedRemoved.removed); + await this._orderStore.updateAsync(addedRemoved); } } diff --git a/packages/orderbook/src/order_provider/custom_order_provider.ts b/packages/orderbook/src/order_provider/custom_order_provider.ts index f47e608f96..f32c865cd5 100644 --- a/packages/orderbook/src/order_provider/custom_order_provider.ts +++ b/packages/orderbook/src/order_provider/custom_order_provider.ts @@ -23,7 +23,7 @@ export class CustomOrderProvider extends BaseOrderProvider { const minAmount = new BigNumber(0); const maxAmount = new BigNumber(2).pow(256).minus(1); const precision = DEFAULT_TOKEN_PRECISION; - for (const assetPairKey of this._orderStore.keys()) { + for (const assetPairKey of await this._orderStore.keysAsync()) { const [assetA, assetB] = OrderStore.assetPairKeyToAssets(assetPairKey); const assetDataA: Asset = { assetData: assetA, minAmount, maxAmount, precision }; const assetDataB: Asset = { assetData: assetB, minAmount, maxAmount, precision }; @@ -40,13 +40,19 @@ export class CustomOrderProvider extends BaseOrderProvider { public async addOrdersAsync(orders: SignedOrder[]): Promise { for (const order of orders) { - const orderSet = this._orderStore.getOrderSetForAssets(order.makerAssetData, order.takerAssetData); - await orderSet.addAsync({ - order, - metaData: { - remainingFillableTakerAssetAmount: order.takerAssetAmount, - orderHash: await utils.getOrderHashAsync(order), - }, + const assetPairKey = OrderStore.getKeyForAssetPair(order.makerAssetData, order.takerAssetData); + await this._orderStore.updateAsync({ + added: [ + { + order, + metaData: { + remainingFillableTakerAssetAmount: order.takerAssetAmount, + orderHash: await utils.getOrderHashAsync(order), + }, + }, + ], + removed: [], + assetPairKey, }); } return { accepted: orders, rejected: [] }; diff --git a/packages/orderbook/src/order_provider/mesh_order_provider.ts b/packages/orderbook/src/order_provider/mesh_order_provider.ts index dc7484c21d..42d742df82 100644 --- a/packages/orderbook/src/order_provider/mesh_order_provider.ts +++ b/packages/orderbook/src/order_provider/mesh_order_provider.ts @@ -65,7 +65,7 @@ export class MeshOrderProvider extends BaseOrderProvider { const minAmount = new BigNumber(0); const maxAmount = new BigNumber(2).pow(256).minus(1); const precision = DEFAULT_TOKEN_PRECISION; - for (const assetPairKey of this._orderStore.keys()) { + for (const assetPairKey of await this._orderStore.keysAsync()) { const [assetA, assetB] = OrderStore.assetPairKeyToAssets(assetPairKey); const assetDataA: Asset = { assetData: assetA, minAmount, maxAmount, precision }; const assetDataB: Asset = { assetData: assetB, minAmount, maxAmount, precision }; @@ -127,8 +127,8 @@ export class MeshOrderProvider extends BaseOrderProvider { * for every known asset pair. */ private async _syncOrdersInOrderStoreAsync(): Promise { - for (const assetPairKey of this._orderStore.keys()) { - const currentOrders = this._orderStore.getOrderSetForAssetPair(assetPairKey); + for (const assetPairKey of await this._orderStore.keysAsync()) { + const currentOrders = await this._orderStore.getOrderSetForAssetPairAsync(assetPairKey); const { rejected } = await utils.attemptAsync(() => this._wsClient.addOrdersAsync(Array.from(currentOrders.values()).map(o => o.order)), ); diff --git a/packages/orderbook/src/order_provider/sra_polling_order_provider.ts b/packages/orderbook/src/order_provider/sra_polling_order_provider.ts index 33a56fb80b..96d8133686 100644 --- a/packages/orderbook/src/order_provider/sra_polling_order_provider.ts +++ b/packages/orderbook/src/order_provider/sra_polling_order_provider.ts @@ -69,7 +69,7 @@ export class SRAPollingOrderProvider extends BaseSRAOrderProvider { const assetPairKey = OrderStore.getKeyForAssetPair(makerAssetData, takerAssetData); const pollingIntervalId = intervalUtils.setAsyncExcludingInterval( async () => { - const previousOrderSet = this._orderStore.getOrderSetForAssetPair(assetPairKey); + const previousOrderSet = await this._orderStore.getOrderSetForAssetPairAsync(assetPairKey); const orders = await this._fetchLatestOrdersAsync(makerAssetData, takerAssetData); const orderSet = new OrderSet(); await orderSet.addManyAsync(orders); diff --git a/packages/orderbook/src/order_provider/sra_websocket_order_provider.ts b/packages/orderbook/src/order_provider/sra_websocket_order_provider.ts index 3f127fb356..1dd123289c 100644 --- a/packages/orderbook/src/order_provider/sra_websocket_order_provider.ts +++ b/packages/orderbook/src/order_provider/sra_websocket_order_provider.ts @@ -101,7 +101,7 @@ export class SRAWebsocketOrderProvider extends BaseSRAOrderProvider { // first time we have had this request, preload the local storage const orders = await this._fetchLatestOrdersAsync(makerAssetData, takerAssetData); const assetPairKey = OrderStore.getKeyForAssetPair(makerAssetData, takerAssetData); - const currentOrders = this._orderStore.getOrderSetForAssetPair(assetPairKey); + const currentOrders = await this._orderStore.getOrderSetForAssetPairAsync(assetPairKey); const newOrders = new OrderSet(); await newOrders.addManyAsync(orders); const diff = await currentOrders.diffAsync(newOrders); @@ -113,7 +113,7 @@ export class SRAWebsocketOrderProvider extends BaseSRAOrderProvider { } private async _syncOrdersInOrderStoreAsync(): Promise { - for (const assetPairKey of this._orderStore.keys()) { + for (const assetPairKey of await this._orderStore.keysAsync()) { const [assetDataA, assetDataB] = OrderStore.assetPairKeyToAssets(assetPairKey); await this._fetchAndCreateSubscriptionAsync(assetDataA, assetDataB); } diff --git a/packages/orderbook/src/order_store.ts b/packages/orderbook/src/order_store.ts index 16c42e3fab..faf1488645 100644 --- a/packages/orderbook/src/order_store.ts +++ b/packages/orderbook/src/order_store.ts @@ -12,11 +12,11 @@ export class OrderStore { public static assetPairKeyToAssets(assetPairKey: string): string[] { return assetPairKey.split('-'); } - public getOrderSetForAssets(makerAssetData: string, takerAssetData: string): OrderSet { + public async getOrderSetForAssetsAsync(makerAssetData: string, takerAssetData: string): Promise { const assetPairKey = OrderStore.getKeyForAssetPair(makerAssetData, takerAssetData); - return this.getOrderSetForAssetPair(assetPairKey); + return this.getOrderSetForAssetPairAsync(assetPairKey); } - public getOrderSetForAssetPair(assetPairKey: string): OrderSet { + public async getOrderSetForAssetPairAsync(assetPairKey: string): Promise { const orderSet = this._orders.get(assetPairKey); if (!orderSet) { const newOrderSet = new OrderSet(); @@ -27,17 +27,17 @@ export class OrderStore { } public async updateAsync(addedRemoved: AddedRemovedOrders): Promise { const { added, removed, assetPairKey } = addedRemoved; - const orders = this.getOrderSetForAssetPair(assetPairKey); + const orders = await this.getOrderSetForAssetPairAsync(assetPairKey); await orders.addManyAsync(added); await orders.deleteManyAsync(removed); } - public has(assetPairKey: string): boolean { + public async hasAsync(assetPairKey: string): Promise { return this._orders.has(assetPairKey); } - public values(assetPairKey: string): APIOrder[] { - return Array.from(this.getOrderSetForAssetPair(assetPairKey).values()); + public async valuesAsync(assetPairKey: string): Promise { + return Array.from((await this.getOrderSetForAssetPairAsync(assetPairKey)).values()); } - public keys(): IterableIterator { + public async keysAsync(): Promise> { return this._orders.keys(); } } diff --git a/packages/orderbook/src/orderbook.ts b/packages/orderbook/src/orderbook.ts index 3cce4ac876..e0fe97f16f 100644 --- a/packages/orderbook/src/orderbook.ts +++ b/packages/orderbook/src/orderbook.ts @@ -76,10 +76,10 @@ export class Orderbook { assert.isString('makerAssetData', makerAssetData); assert.isString('takerAssetData', takerAssetData); const assetPairKey = OrderStore.getKeyForAssetPair(makerAssetData, takerAssetData); - if (!this._orderStore.has(assetPairKey)) { + if (!(await this._orderStore.hasAsync(assetPairKey))) { await this._orderProvider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); } - const orders = this._orderStore.values(assetPairKey); + const orders = await this._orderStore.valuesAsync(assetPairKey); return orders.filter( o => o.order.makerAssetData === makerAssetData && o.order.takerAssetData === takerAssetData, ); diff --git a/packages/orderbook/test/order_provider/mesh_order_provider.test.ts b/packages/orderbook/test/order_provider/mesh_order_provider.test.ts index 40745d0bb5..ab9d8c5fcc 100644 --- a/packages/orderbook/test/order_provider/mesh_order_provider.test.ts +++ b/packages/orderbook/test/order_provider/mesh_order_provider.test.ts @@ -142,7 +142,7 @@ describe('MeshOrderProvider', () => { ); provider = new MeshOrderProvider({ websocketEndpoint }, orderStore); await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); - const orders = orderStore.getOrderSetForAssets(makerAssetData, takerAssetData); + const orders = await orderStore.getOrderSetForAssetsAsync(makerAssetData, takerAssetData); expect(orders.size()).toBe(1); }); test('stores the orders from a subscription update', async () => { @@ -152,7 +152,7 @@ describe('MeshOrderProvider', () => { await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); connection.sendUTF(eventResponse); await utils.delayAsync(100); - const orders = orderStore.getOrderSetForAssets(makerAssetData, takerAssetData); + const orders = await orderStore.getOrderSetForAssetsAsync(makerAssetData, takerAssetData); expect(orders.size()).toBe(1); }); test('removes orders on a subscription update', async () => { @@ -163,7 +163,7 @@ describe('MeshOrderProvider', () => { await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); connection.sendUTF(added); await utils.delayAsync(100); - const orders = orderStore.getOrderSetForAssets(makerAssetData, takerAssetData); + const orders = await orderStore.getOrderSetForAssetsAsync(makerAssetData, takerAssetData); expect(orders.size()).toBe(1); connection.sendUTF(removed); await utils.delayAsync(100); @@ -224,7 +224,7 @@ describe('MeshOrderProvider', () => { orderStore, ); await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); - const orders = orderStore.getOrderSetForAssets(makerAssetData, takerAssetData); + const orders = await orderStore.getOrderSetForAssetsAsync(makerAssetData, takerAssetData); expect(getOrdersStub.callCount).toBe(1); // Orders are not added on a subscription, only during reconnnect expect(addOrdersStub.callCount).toBe(0); diff --git a/packages/orderbook/test/order_provider/sra_polling_order_provider.test.ts b/packages/orderbook/test/order_provider/sra_polling_order_provider.test.ts index 875819bba1..a014778c41 100644 --- a/packages/orderbook/test/order_provider/sra_polling_order_provider.test.ts +++ b/packages/orderbook/test/order_provider/sra_polling_order_provider.test.ts @@ -71,7 +71,7 @@ describe('SRAPollingOrderProvider', () => { ); provider = new SRAPollingOrderProvider({ httpEndpoint, pollingIntervalMs: 30000 }, orderStore); await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); - const orders = orderStore.getOrderSetForAssets(makerAssetData, takerAssetData); + const orders = await orderStore.getOrderSetForAssetsAsync(makerAssetData, takerAssetData); expect(orders.size()).toBe(1); }); test('removes the order from the set when the API response no longer returns the order', async () => { @@ -88,7 +88,7 @@ describe('SRAPollingOrderProvider', () => { ); provider = new SRAPollingOrderProvider({ httpEndpoint, pollingIntervalMs: 1 }, orderStore); await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); - const orders = orderStore.getOrderSetForAssets(makerAssetData, takerAssetData); + const orders = await orderStore.getOrderSetForAssetsAsync(makerAssetData, takerAssetData); expect(orders.size()).toBe(1); // Delete the record from the API response records.splice(0, 1); diff --git a/packages/orderbook/test/order_provider/sra_websocket_order_provider.test.ts b/packages/orderbook/test/order_provider/sra_websocket_order_provider.test.ts index fa35782d04..36e150df82 100644 --- a/packages/orderbook/test/order_provider/sra_websocket_order_provider.test.ts +++ b/packages/orderbook/test/order_provider/sra_websocket_order_provider.test.ts @@ -87,7 +87,7 @@ describe('SRAWebsocketOrderProvider', () => { expect(stub.callCount).toBe(2); expect(wsStub.callCount).toBe(1); await utils.delayAsync(5); - const storedOrders = orderStore.getOrderSetForAssets(makerAssetData, takerAssetData); + const storedOrders = await orderStore.getOrderSetForAssetsAsync(makerAssetData, takerAssetData); expect(storedOrders.size()).toBe(1); }); test('stores the orders', async () => { @@ -108,7 +108,7 @@ describe('SRAWebsocketOrderProvider', () => { ); provider = new SRAWebsocketOrderProvider({ httpEndpoint, websocketEndpoint }, orderStore); await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); - const orders = orderStore.getOrderSetForAssets(makerAssetData, takerAssetData); + const orders = await orderStore.getOrderSetForAssetsAsync(makerAssetData, takerAssetData); expect(orders.size()).toBe(1); }); test('reconnects on channel close', async () => { @@ -134,6 +134,7 @@ describe('SRAWebsocketOrderProvider', () => { await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); expect(handler).not.toBe(undefined); (handler as OrdersChannelHandler).onClose(undefined as any); + await utils.delayAsync(5); // Creates the new connection expect(wsStub.callCount).toBe(2); });