From 4abbb53dd66bfd514e3eb8270165b1dae297e769 Mon Sep 17 00:00:00 2001 From: Craig Bovis Date: Sat, 19 Sep 2020 19:24:48 +0200 Subject: [PATCH] Introduce job for indexing fill traders (#458) * Add new job type to constants * Start creating job for indexing fill traders * Finish test suite and fix a couple of bugs * Index traders after fill creation --- src/constants.js | 1 + src/consumers/index-fill-traders/index.js | 113 ++++ .../index-fill-traders/index.test.js | 485 ++++++++++++++++++ src/consumers/index.js | 2 + src/fills/create-fills.js | 10 +- src/index/index-fill-traders.js | 38 ++ src/jobs/create-fills/create-fill.test.js | 14 + 7 files changed, 659 insertions(+), 4 deletions(-) create mode 100644 src/consumers/index-fill-traders/index.js create mode 100644 src/consumers/index-fill-traders/index.test.js create mode 100644 src/index/index-fill-traders.js diff --git a/src/constants.js b/src/constants.js index 53606181c..321899b8c 100644 --- a/src/constants.js +++ b/src/constants.js @@ -65,6 +65,7 @@ module.exports = { INDEX_APP_FILL_ATTRIBUTONS: 'index-app-fill-attributions', INDEX_FILL: 'index-fill', INDEX_FILL_PROTOCOL_FEE: 'index-fill-protocol-fee', + INDEX_FILL_TRADERS: 'index-fill-traders', INDEX_FILL_VALUE: 'index-fill-value', INDEX_TRADED_TOKENS: 'index-traded-tokens', }, diff --git a/src/consumers/index-fill-traders/index.js b/src/consumers/index-fill-traders/index.js new file mode 100644 index 000000000..ebbb1c555 --- /dev/null +++ b/src/consumers/index-fill-traders/index.js @@ -0,0 +1,113 @@ +const _ = require('lodash'); + +const { JOB, QUEUE } = require('../../constants'); +const { publishJob } = require('../../queues'); +const elasticsearch = require('../../util/elasticsearch'); +const getAddressMetadata = require('../../addresses/get-address-metadata'); +const getTransactionByHash = require('../../transactions/get-transaction-by-hash'); + +const indexFillTraders = async (job, { logger }) => { + const delayJobProcessing = async () => { + await publishJob(QUEUE.INDEXING, JOB.INDEX_FILL_TRADERS, job.data, { + delay: 30000, + }); + }; + + const { + fillDate, + fillId, + fillValue, + maker, + taker, + tradeCount, + transactionHash, + } = job.data; + + const takerMetadata = await getAddressMetadata(taker); + + if (takerMetadata === null || takerMetadata.isContract === undefined) { + logger.warn(`taker address type is unknown: ${taker}`); + await delayJobProcessing(); + + return; + } + + let transaction; + + if (takerMetadata.isContract) { + transaction = await getTransactionByHash(transactionHash); + + if (transaction === null) { + logger.warn(`transaction has not been fetched: ${transactionHash}`); + await delayJobProcessing(); + + return; + } + } + + const tradeValue = + fillValue === undefined ? undefined : fillValue * tradeCount; + + const requestBody = [ + JSON.stringify({ + index: { + _id: `${fillId}_maker`, + }, + }), + JSON.stringify({ + address: maker, + fillId, + date: fillDate, + makerFillCount: 1, + makerFillValue: fillValue, + makerTradeCount: tradeCount, + makerTradeValue: tradeValue, + totalFillCount: 1, + totalFillValue: fillValue, + totalTradeCount: tradeCount, + totalTradeValue: tradeValue, + updatedAt: new Date().toISOString(), + }), + JSON.stringify({ + index: { + _id: `${fillId}_taker`, + }, + }), + JSON.stringify({ + address: takerMetadata.isContract ? transaction.from : taker, + fillId, + date: fillDate, + takerFillCount: 1, + takerFillValue: fillValue, + takerTradeCount: tradeCount, + takerTradeValue: tradeValue, + totalFillCount: 1, + totalFillValue: fillValue, + totalTradeCount: tradeCount, + totalTradeValue: tradeValue, + updatedAt: new Date().toISOString(), + }), + ].join('\n'); + + const result = await elasticsearch + .getClient() + .bulk({ body: `${requestBody}\n`, index: 'trader_fills' }); + + if (result.body.errors === true) { + const errorMessage = _.get( + result, + 'body.items[0].index.error.reason', + `Failed to index trader_fills`, + ); + + throw new Error(errorMessage); + } + + logger.info(`indexed fill traders: ${fillId}`); +}; + +module.exports = { + fn: indexFillTraders, + jobName: JOB.INDEX_FILL_TRADERS, + queueName: QUEUE.INDEXING, +}; diff --git a/src/consumers/index-fill-traders/index.test.js b/src/consumers/index-fill-traders/index.test.js new file mode 100644 index 000000000..bd01f1b3e --- /dev/null +++ b/src/consumers/index-fill-traders/index.test.js @@ -0,0 +1,485 @@ +const { Client } = require('@elastic/elasticsearch'); +const Mock = require('@elastic/elasticsearch-mock'); +const timekeeper = require('timekeeper'); + +const { getModel } = require('../../model'); +const { + mockLogger, + resetDb, + setupDb, + tearDownDb, +} = require('../../test-utils'); +const { publishJob } = require('../../queues'); +const elasticsearch = require('../../util/elasticsearch'); +const consumer = require('.'); + +jest.mock('../../queues'); +jest.mock('../../util/elasticsearch'); + +const elasticsearchMock = new Mock(); +const mockOptions = { + logger: mockLogger, +}; + +beforeAll(async () => { + const client = new Client({ + node: 'http://localhost:9200', + Connection: elasticsearchMock.getConnection(), + }); + + elasticsearch.getClient.mockReturnValue(client); + await setupDb(); +}, 30000); + +beforeEach(() => { + timekeeper.freeze('2020-08-02T08:42:24.934Z'); +}); + +afterEach(async () => { + jest.clearAllMocks(); + await resetDb(); + elasticsearchMock.clearAll(); +}, 30000); + +afterAll(async () => { + await tearDownDb(); +}, 30000); + +describe('consumers/index-fill-traders', () => { + it('should consume indexing queue', () => { + expect(consumer.queueName).toBe('indexing'); + }); + + it('should consume index-fill-traders jobs', () => { + expect(consumer.jobName).toBe('index-fill-traders'); + }); + + it('should delay job processing when taker type unknown', async () => { + const job = { + data: { + fillDate: new Date('2020-08-02T07:47:28Z'), + fillId: '5f267c7b545e125452c56e14', + fillValue: 500, + maker: '0x903153f55770b7668a497180f7fa93471545ffe2', + taker: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + tradeCount: 1, + transactionHash: + '0x165a1b8f4fbcf089e48435c2efef12dab5223c560f067f932c8efc3d7c6d74eb', + }, + }; + + await consumer.fn(job, mockOptions); + + expect(mockLogger.warn).toHaveBeenCalledTimes(1); + expect(mockLogger.warn).toHaveBeenCalledWith( + 'taker address type is unknown: 0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + ); + + expect(publishJob).toHaveBeenCalledTimes(1); + expect(publishJob).toHaveBeenCalledWith( + 'indexing', + 'index-fill-traders', + job.data, + { delay: 30000 }, + ); + }); + + it('should delay job processing when taker is contract and associated transaction not fetched', async () => { + const job = { + data: { + fillDate: new Date('2020-08-02T07:47:28Z'), + fillId: '5f267c7b545e125452c56e14', + fillValue: 500, + maker: '0x903153f55770b7668a497180f7fa93471545ffe2', + taker: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + tradeCount: 1, + transactionHash: + '0x165a1b8f4fbcf089e48435c2efef12dab5223c560f067f932c8efc3d7c6d74eb', + }, + }; + + const AddressMetadata = getModel('AddressMetadata'); + + await AddressMetadata.create({ + address: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + isContract: true, + }); + + await consumer.fn(job, mockOptions); + + expect(mockLogger.warn).toHaveBeenCalledTimes(1); + expect(mockLogger.warn).toHaveBeenCalledWith( + 'transaction has not been fetched: 0x165a1b8f4fbcf089e48435c2efef12dab5223c560f067f932c8efc3d7c6d74eb', + ); + + expect(publishJob).toHaveBeenCalledTimes(1); + expect(publishJob).toHaveBeenCalledWith( + 'indexing', + 'index-fill-traders', + job.data, + { delay: 30000 }, + ); + }); + + it('should index maker & taker when taker address is not a contract', async () => { + const job = { + data: { + fillDate: new Date('2020-08-02T07:47:28Z'), + fillId: '5f267c7b545e125452c56e14', + fillValue: 500, + maker: '0x903153f55770b7668a497180f7fa93471545ffe2', + taker: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + tradeCount: 1, + transactionHash: + '0x165a1b8f4fbcf089e48435c2efef12dab5223c560f067f932c8efc3d7c6d74eb', + }, + }; + + const AddressMetadata = getModel('AddressMetadata'); + let indexingBody; + + elasticsearchMock.add( + { + method: 'POST', + path: '/trader_fills/_bulk', + }, + ({ body }) => { + indexingBody = body; + + return { status: 'ok' }; + }, + ); + + await AddressMetadata.create({ + address: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + isContract: false, + }); + + await consumer.fn(job, mockOptions); + + expect(indexingBody).toEqual([ + { + index: { + _id: '5f267c7b545e125452c56e14_maker', + }, + }, + { + address: '0x903153f55770b7668a497180f7fa93471545ffe2', + fillId: '5f267c7b545e125452c56e14', + date: '2020-08-02T07:47:28.000Z', + makerFillCount: 1, + makerFillValue: 500, + makerTradeCount: 1, + makerTradeValue: 500, + totalFillCount: 1, + totalFillValue: 500, + totalTradeCount: 1, + totalTradeValue: 500, + updatedAt: '2020-08-02T08:42:24.934Z', + }, + { + index: { + _id: '5f267c7b545e125452c56e14_taker', + }, + }, + { + address: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + fillId: '5f267c7b545e125452c56e14', + date: '2020-08-02T07:47:28.000Z', + takerFillCount: 1, + takerFillValue: 500, + takerTradeCount: 1, + takerTradeValue: 500, + totalFillCount: 1, + totalFillValue: 500, + totalTradeCount: 1, + totalTradeValue: 500, + updatedAt: '2020-08-02T08:42:24.934Z', + }, + ]); + }); + + it('should index maker & transaction sender when taker is a contract', async () => { + const job = { + data: { + fillDate: new Date('2020-08-02T07:47:28Z'), + fillId: '5f661ee4e5267d16e5a70c36', + fillValue: 500, + maker: '0x5e8d405cbc564473d85a9a31fbfca76167d69978', + taker: '0xe33c8e3a0d14a81f0dd7e174830089e82f65fc85', + tradeCount: 1, + transactionHash: + '0x6daec6c63e8c96130f04711409970ead1ec9fdc778090917d8eea7cab140520e', + }, + }; + + const AddressMetadata = getModel('AddressMetadata'); + const Transaction = getModel('Transaction'); + + let indexingBody; + + elasticsearchMock.add( + { + method: 'POST', + path: '/trader_fills/_bulk', + }, + ({ body }) => { + indexingBody = body; + + return { status: 'ok' }; + }, + ); + + await AddressMetadata.create({ + address: '0xe33c8e3a0d14a81f0dd7e174830089e82f65fc85', + isContract: true, + }); + + await Transaction.create({ + blockHash: + '0xb7a0059c1aff2e84f7d5b75dd29b57325bd6a8dd0469240689cc52df1df1146a', + blockNumber: 10893374, + data: + '0x000d070a11ced27fd19c7a2bc70fd72adb55bb7025014e00000000000000000000d3d2e2692501a5c9ca623199d38826e513033a17000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f984000000000000000000000000e33c8e3a0d14a81f0dd7e174830089e82f65fc85000000000000000000000000000000000000000000000003255b68cdf304cdc40000000000000000000000000000000000000000000000031e171c6104e502420000000000000000000000000000000000000000000000101ad5ea23c2190000014e000000000000000000005e8d405cbc564473d85a9a31fbfca76167d6997800000000000000000000000086003b044f70dac0abc80ac8957305b6370893ed00000000000000000000000000000000000000000000001043561a882930000000000000000000000000000000000000000000000000039f985e76e5df87c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f6a05b9b3bb06a8e0c998ead8e30362e7663c1ab2b85d3819bb855485663c92da4296270000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f984000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b0622adacaeaa57d837c0c7b0814cdabc77dd8997985b753898ace8c7ac4f153a0e888a244c75b330dec0b609daf4a2d1734b7b8e8f95fac8f0845de2b4ee25a602000000000000000000000000000000000000000000000000000000000000727282747ecf0f1e02c1d91b592077453ccaa8aead781317f80b2e6de158b24f00000000000000000000000000000000000000000000039f95fe8e3fc3400000', + date: new Date('2020-09-19T15:04:28.000Z'), + from: '0xff59364722a4622a8d33623548926375b1b07767', + gasLimit: 380000, + gasPrice: '333000000000', + gasUsed: 261241, + hash: + '0x6daec6c63e8c96130f04711409970ead1ec9fdc778090917d8eea7cab140520e', + index: 23, + nonce: '83376', + to: '0xe33c8e3a0d14a81f0dd7e174830089e82f65fc85', + value: '0', + }); + + await consumer.fn(job, mockOptions); + + expect(indexingBody).toEqual([ + { + index: { + _id: '5f661ee4e5267d16e5a70c36_maker', + }, + }, + { + address: '0x5e8d405cbc564473d85a9a31fbfca76167d69978', + fillId: '5f661ee4e5267d16e5a70c36', + date: '2020-08-02T07:47:28.000Z', + makerFillCount: 1, + makerFillValue: 500, + makerTradeCount: 1, + makerTradeValue: 500, + totalFillCount: 1, + totalFillValue: 500, + totalTradeCount: 1, + totalTradeValue: 500, + updatedAt: '2020-08-02T08:42:24.934Z', + }, + { + index: { + _id: '5f661ee4e5267d16e5a70c36_taker', + }, + }, + { + address: '0xff59364722a4622a8d33623548926375b1b07767', + fillId: '5f661ee4e5267d16e5a70c36', + date: '2020-08-02T07:47:28.000Z', + takerFillCount: 1, + takerFillValue: 500, + takerTradeCount: 1, + takerTradeValue: 500, + totalFillCount: 1, + totalFillValue: 500, + totalTradeCount: 1, + totalTradeValue: 500, + updatedAt: '2020-08-02T08:42:24.934Z', + }, + ]); + }); + + it('should index without value if not available', async () => { + const job = { + data: { + fillDate: new Date('2020-08-02T07:47:28Z'), + fillId: '5f267c7b545e125452c56e14', + maker: '0x903153f55770b7668a497180f7fa93471545ffe2', + taker: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + tradeCount: 1, + transactionHash: + '0x165a1b8f4fbcf089e48435c2efef12dab5223c560f067f932c8efc3d7c6d74eb', + }, + }; + + const AddressMetadata = getModel('AddressMetadata'); + let indexingBody; + + elasticsearchMock.add( + { + method: 'POST', + path: '/trader_fills/_bulk', + }, + ({ body }) => { + indexingBody = body; + + return { status: 'ok' }; + }, + ); + + await AddressMetadata.create({ + address: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + isContract: false, + }); + + await consumer.fn(job, mockOptions); + + expect(indexingBody).toEqual([ + { + index: { + _id: '5f267c7b545e125452c56e14_maker', + }, + }, + { + address: '0x903153f55770b7668a497180f7fa93471545ffe2', + fillId: '5f267c7b545e125452c56e14', + date: '2020-08-02T07:47:28.000Z', + makerFillCount: 1, + makerTradeCount: 1, + totalFillCount: 1, + totalTradeCount: 1, + updatedAt: '2020-08-02T08:42:24.934Z', + }, + { + index: { + _id: '5f267c7b545e125452c56e14_taker', + }, + }, + { + address: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + fillId: '5f267c7b545e125452c56e14', + date: '2020-08-02T07:47:28.000Z', + takerFillCount: 1, + takerTradeCount: 1, + totalFillCount: 1, + totalTradeCount: 1, + updatedAt: '2020-08-02T08:42:24.934Z', + }, + ]); + }); + + it('should index correct trade value when fill is partial', async () => { + const job = { + data: { + fillDate: new Date('2020-08-02T07:47:28Z'), + fillId: '5f267c7b545e125452c56e14', + fillValue: 500, + maker: '0x903153f55770b7668a497180f7fa93471545ffe2', + taker: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + tradeCount: 0.5, + transactionHash: + '0x165a1b8f4fbcf089e48435c2efef12dab5223c560f067f932c8efc3d7c6d74eb', + }, + }; + + const AddressMetadata = getModel('AddressMetadata'); + let indexingBody; + + elasticsearchMock.add( + { + method: 'POST', + path: '/trader_fills/_bulk', + }, + ({ body }) => { + indexingBody = body; + + return { status: 'ok' }; + }, + ); + + await AddressMetadata.create({ + address: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + isContract: false, + }); + + await consumer.fn(job, mockOptions); + + expect(indexingBody).toEqual([ + { + index: { + _id: '5f267c7b545e125452c56e14_maker', + }, + }, + { + address: '0x903153f55770b7668a497180f7fa93471545ffe2', + fillId: '5f267c7b545e125452c56e14', + date: '2020-08-02T07:47:28.000Z', + makerFillCount: 1, + makerFillValue: 500, + makerTradeCount: 0.5, + makerTradeValue: 250, + totalFillCount: 1, + totalFillValue: 500, + totalTradeCount: 0.5, + totalTradeValue: 250, + updatedAt: '2020-08-02T08:42:24.934Z', + }, + { + index: { + _id: '5f267c7b545e125452c56e14_taker', + }, + }, + { + address: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + fillId: '5f267c7b545e125452c56e14', + date: '2020-08-02T07:47:28.000Z', + takerFillCount: 1, + takerFillValue: 500, + takerTradeCount: 0.5, + takerTradeValue: 250, + totalFillCount: 1, + totalFillValue: 500, + totalTradeCount: 0.5, + totalTradeValue: 250, + updatedAt: '2020-08-02T08:42:24.934Z', + }, + ]); + }); + + it('should write log entry on successful completion', async () => { + const job = { + data: { + fillDate: new Date('2020-08-02T07:47:28Z'), + fillId: '5f267c7b545e125452c56e14', + maker: '0x903153f55770b7668a497180f7fa93471545ffe2', + taker: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + tradeCount: 1, + transactionHash: + '0x165a1b8f4fbcf089e48435c2efef12dab5223c560f067f932c8efc3d7c6d74eb', + }, + }; + + const AddressMetadata = getModel('AddressMetadata'); + + elasticsearchMock.add( + { + method: 'POST', + path: '/trader_fills/_bulk', + }, + () => { + return { status: 'ok' }; + }, + ); + + await AddressMetadata.create({ + address: '0xd0f8715fda0c1b564c2087315fb55804eaf1fae9', + isContract: false, + }); + + await consumer.fn(job, mockOptions); + + expect(mockLogger.info).toHaveBeenCalledTimes(1); + expect(mockLogger.info).toHaveBeenCalledWith( + 'indexed fill traders: 5f267c7b545e125452c56e14', + ); + }); +}); diff --git a/src/consumers/index.js b/src/consumers/index.js index 5a85e00f5..ecb2d2453 100644 --- a/src/consumers/index.js +++ b/src/consumers/index.js @@ -13,6 +13,7 @@ const fetchTransaction = require('./fetch-transaction'); const indexAppFillAttributions = require('./index-app-fill-attributions'); const indexFill = require('./index-fill'); const indexFillProtocolFee = require('./index-fill-protocol-fee'); +const indexFillTraders = require('./index-fill-traders'); const indexFillValue = require('./index-fill-value'); const indexTradedTokens = require('./index-traded-tokens'); @@ -28,6 +29,7 @@ const consumers = [ indexAppFillAttributions, indexFill, indexFillProtocolFee, + indexFillTraders, indexFillValue, indexTradedTokens, ]; diff --git a/src/fills/create-fills.js b/src/fills/create-fills.js index eebe26755..9d5f4d2eb 100644 --- a/src/fills/create-fills.js +++ b/src/fills/create-fills.js @@ -7,13 +7,14 @@ const { JOB, QUEUE } = require('../constants'); const { publishJob } = require('../queues'); const applyAttributionsToFill = require('./apply-attributions-to-fill'); const convertProtocolFee = require('../fills/convert-protocol-fee'); +const convertRelayerFees = require('./convert-relayer-fees'); const fetchUnknownAddressTypes = require('../addresses/fetch-unknown-address-types'); -const indexFill = require('../index/index-fill'); -const indexTradedTokens = require('../index/index-traded-tokens'); +const getAppAttributionsForFill = require('./get-app-attributions-for-fill'); const hasProtocolFee = require('./has-protocol-fee'); const hasRelayerFees = require('./has-relayer-fees'); -const convertRelayerFees = require('./convert-relayer-fees'); -const getAppAttributionsForFill = require('./get-app-attributions-for-fill'); +const indexFill = require('../index/index-fill'); +const indexFillTraders = require('../index/index-fill-traders'); +const indexTradedTokens = require('../index/index-traded-tokens'); const createFills = async (fills, { session }) => { const attributedFills = fills.map(fill => applyAttributionsToFill(fill)); @@ -63,6 +64,7 @@ const createFills = async (fills, { session }) => { await indexFill(fillId, ms('30 seconds')); await indexTradedTokens(fill); + await indexFillTraders(fill); if (hasProtocolFee(fill)) { await convertProtocolFee(fill, ms('30 seconds')); diff --git a/src/index/index-fill-traders.js b/src/index/index-fill-traders.js new file mode 100644 index 000000000..47b4acefd --- /dev/null +++ b/src/index/index-fill-traders.js @@ -0,0 +1,38 @@ +const _ = require('lodash'); +const { JOB, QUEUE } = require('../constants'); +const { publishJob } = require('../queues'); +const relayerRegistry = require('../relayers/relayer-registry'); + +const isOrderMatcher = relayerId => { + const relayer = _(relayerRegistry) + .values() + .find({ lookupId: relayerId }); + + return _.get(relayer, 'orderMatcher', false); +}; + +const calculateTradeCount = relayerId => { + if (isOrderMatcher(relayerId)) { + return 0.5; + } + + return 1; +}; + +const indexFillTraders = async fill => { + const fillId = fill._id.toString(); + const value = _.get(fill, 'conversions.USD.amount'); + const tradeCount = calculateTradeCount(fill.relayerId); + + publishJob(QUEUE.INDEXING, JOB.INDEX_FILL_TRADERS, { + fillDate: fill.date, + fillId, + fillValue: value, + maker: fill.maker, + taker: fill.taker, + tradeCount, + transactionHash: fill.transactionHash, + }); +}; + +module.exports = indexFillTraders; diff --git a/src/jobs/create-fills/create-fill.test.js b/src/jobs/create-fills/create-fill.test.js index 96373a8bd..d1e03abf7 100644 --- a/src/jobs/create-fills/create-fill.test.js +++ b/src/jobs/create-fills/create-fill.test.js @@ -433,6 +433,20 @@ describe('createFill', () => { ); }); + it('should index fill traders after creation', async () => { + await createFill(V3_EVENT, simpleTransaction); + + expect(publishJob).toHaveBeenCalledWith('indexing', 'index-fill-traders', { + fillDate: new Date('2019-10-26T16:32:03.000Z'), + fillId: '5bb1f06b62f9ca0004c7cf20', + maker: '0xd3d0474124c1013ed6bfcfd9a49cfedb8c78fc44', + taker: '0x7447dab10325f902725191a34eb8288abe02c7f4', + tradeCount: 1, + transactionHash: + '0x00cfc187cce6c5f537f84621b6fce4ac828848f2b088b16f0deeb4bde2586637', + }); + }); + // TODO: Reintroduce these tests in a future PR // it('should only create tokens which do not already exist', async () => { // getExistingTokens.mockResolvedValue([