import { HttpClient } from '@0x/connect'; import * as sinon from 'sinon'; import { SRAPollingOrderProvider } from '../../src'; import { BaseOrderProvider } from '../../src/order_provider/base_order_provider'; import { OrderStore } from '../../src/order_store'; import { utils } from '../../src/utils'; import { createOrder } from '../utils'; describe('SRAPollingOrderProvider', () => { let orderStore: OrderStore; let provider: BaseOrderProvider; const httpEndpoint = 'https://localhost'; const makerAssetData = '0xf47261b000000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359'; const takerAssetData = '0xf47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'; const stubs: sinon.SinonStub[] = []; afterEach(() => { void provider.destroyAsync(); stubs.forEach(s => s.restore()); }); beforeEach(() => { orderStore = new OrderStore(); }); describe('#createSubscriptionForAssetPairAsync', () => { test('fetches order on first subscription', async () => { const stub = sinon .stub(HttpClient.prototype, 'getOrdersAsync') .callsFake(async () => Promise.resolve({ records: [], total: 0, perPage: 0, page: 1 })); stubs.push(stub); provider = new SRAPollingOrderProvider({ httpEndpoint, pollingIntervalMs: 5 }, orderStore); await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); expect(stub.callCount).toBe(2); }); test('fetches once when the same subscription is created', async () => { const stub = sinon .stub(HttpClient.prototype, 'getOrdersAsync') .callsFake(async () => Promise.resolve({ records: [], total: 0, perPage: 0, page: 1 })); stubs.push(stub); provider = new SRAPollingOrderProvider({ httpEndpoint, pollingIntervalMs: 5 }, orderStore); await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); expect(stub.callCount).toBe(2); }); test('periodically polls for orders', async () => { const stub = sinon.stub(HttpClient.prototype, 'getOrdersAsync').callsFake(async () => Promise.resolve({ records: [createOrder(makerAssetData, takerAssetData)], total: 1, perPage: 1, page: 1, }), ); stubs.push(stub); provider = new SRAPollingOrderProvider({ httpEndpoint, pollingIntervalMs: 1 }, orderStore); await provider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); await utils.delayAsync(5); expect(stub.callCount).toBeGreaterThan(2); }); test('stores the orders returned from the API response', async () => { const records = [createOrder(makerAssetData, takerAssetData)]; stubs.push( sinon.stub(HttpClient.prototype, 'getOrdersAsync').callsFake(async () => Promise.resolve({ records, total: 1, perPage: 1, page: 1, }), ), ); provider = new SRAPollingOrderProvider({ httpEndpoint, pollingIntervalMs: 30000 }, orderStore); await provider.createSubscriptionForAssetPairAsync(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 () => { const records = [createOrder(makerAssetData, takerAssetData)]; stubs.push( sinon.stub(HttpClient.prototype, 'getOrdersAsync').callsFake(async () => Promise.resolve({ records, total: 1, perPage: 1, page: 1, }), ), ); provider = new SRAPollingOrderProvider({ httpEndpoint, pollingIntervalMs: 1 }, orderStore); await provider.createSubscriptionForAssetPairAsync(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); await utils.delayAsync(5); expect(orders.size()).toBe(0); }); }); });