Skip to content
This repository was archived by the owner on Aug 12, 2023. It is now read-only.

Commit fa45476

Browse files
authored
Index transaction for fills with contract takers (#463)
* Add virtuals to fill model * Index transaction sender for contract takers
1 parent 86ff818 commit fa45476

5 files changed

Lines changed: 354 additions & 9 deletions

File tree

src/consumers/index-fill.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ const indexFill = async (job, { logger }) => {
1414

1515
logger.info(`indexing fill: ${fillId}`);
1616

17-
const fill = await getModel('Fill').findOne({ _id: fillId });
17+
const fill = await getModel('Fill')
18+
.findOne({ _id: fillId })
19+
.populate([
20+
{ path: 'takerMetadata', select: 'isContract' },
21+
{ path: 'transaction', select: 'from' },
22+
]);
1823

1924
if (fill === null) {
2025
throw new Error(`No fill found with the id: ${fillId}`);
@@ -26,7 +31,7 @@ const indexFill = async (job, { logger }) => {
2631
body: fillsIndex.createDocument(fill),
2732
});
2833

29-
logger.success(`indexed fill: ${fillId}`);
34+
logger.info(`indexed fill: ${fillId}`);
3035
};
3136

3237
module.exports = {

src/consumers/index-fill.test.js

Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
const { Client } = require('@elastic/elasticsearch');
2+
const Mock = require('@elastic/elasticsearch-mock');
3+
const timekeeper = require('timekeeper');
4+
5+
const { getModel } = require('../model');
6+
const { mockLogger, resetDb, setupDb, tearDownDb } = require('../test-utils');
7+
const consumer = require('./index-fill');
8+
const elasticsearch = require('../util/elasticsearch');
9+
10+
jest.mock('../util/elasticsearch');
11+
12+
const elasticsearchMock = new Mock();
13+
const mockOptions = {
14+
logger: mockLogger,
15+
};
16+
17+
beforeAll(async () => {
18+
const client = new Client({
19+
node: 'http://localhost:9200',
20+
Connection: elasticsearchMock.getConnection(),
21+
});
22+
23+
elasticsearch.getClient.mockReturnValue(client);
24+
await setupDb();
25+
}, 30000);
26+
27+
beforeEach(() => {
28+
timekeeper.freeze('2020-08-02T08:42:24.934Z');
29+
});
30+
31+
afterEach(async () => {
32+
jest.clearAllMocks();
33+
await resetDb();
34+
elasticsearchMock.clearAll();
35+
}, 30000);
36+
37+
afterAll(async () => {
38+
await tearDownDb();
39+
}, 30000);
40+
41+
describe('consumers/index-fill', () => {
42+
it('should consume indexing queue', () => {
43+
expect(consumer.queueName).toBe('fill-indexing');
44+
});
45+
46+
it('should consume index-fill-traders jobs', () => {
47+
expect(consumer.jobName).toBe('index-fill');
48+
});
49+
50+
it('should throw an error if fillId is invalid', async () => {
51+
await expect(
52+
consumer.fn(
53+
{
54+
data: {
55+
fillId: 'fubar',
56+
},
57+
},
58+
mockOptions,
59+
),
60+
).rejects.toThrow(new Error('Invalid fillId: fubar'));
61+
});
62+
63+
it('should throw an error if fill cannot be found', async () => {
64+
await expect(
65+
consumer.fn(
66+
{
67+
data: {
68+
fillId: '5f7b709a5a345268dec8d425',
69+
},
70+
},
71+
mockOptions,
72+
),
73+
).rejects.toThrow(
74+
new Error('No fill found with the id: 5f7b709a5a345268dec8d425'),
75+
);
76+
});
77+
78+
it('should index fill when found', async () => {
79+
const AddressMetadata = getModel('AddressMetadata');
80+
const Fill = getModel('Fill');
81+
82+
await AddressMetadata.create({
83+
address: '0xf9757222770d93f0f71c30098d12d4754209f4d4',
84+
isContract: false,
85+
});
86+
87+
await Fill.create({
88+
_id: '5f7b709a5a345268dec8d425',
89+
hasValue: true,
90+
immeasurable: false,
91+
status: 1,
92+
affiliateAddress: '0x86003b044f70dac0abc80ac8957305b6370893ed',
93+
assets: [
94+
{
95+
tokenResolved: true,
96+
amount: 1.41584999559191e21,
97+
tokenAddress: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984',
98+
bridgeAddress: '0xc47b7094f378e54347e281aab170e8cca69d880a',
99+
bridgeData:
100+
'0x0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000047ed0262a0b688dcb836d254c6a2e96b6c48a9f50000000000000000000000000000000000000000000001075064e6a4615ec00000000000000000000000000000000000000000000000004cc0dda57efe13cfa0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000d9e1ce17f2641f24ae83637ab66a2cca9c378b9f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f984',
101+
actor: 0,
102+
price: {
103+
USD: 3.46495715102154,
104+
},
105+
value: {
106+
USD: 4905.859567,
107+
},
108+
},
109+
{
110+
tokenResolved: true,
111+
amount: 4.8572867e21,
112+
tokenAddress: '0x6b175474e89094c44da98b954eedeac495271d0f',
113+
actor: 1,
114+
price: {
115+
USD: 1.01,
116+
},
117+
value: {
118+
USD: 4905.859567,
119+
},
120+
},
121+
],
122+
blockHash:
123+
'0x48d886d6a92fd8515963dab0ea79273b7aa0af3f5a7efeafd8bf1288f80b07b0',
124+
blockNumber: 10997543,
125+
date: new Date('2020-10-05T19:10:18.000Z'),
126+
eventId: '5f7b709a5a345268dec8d425',
127+
fees: [],
128+
feeRecipient: '0x1000000000000000000000000000000000000011',
129+
logIndex: 264,
130+
maker: '0xc47b7094f378e54347e281aab170e8cca69d880a',
131+
orderHash:
132+
'0x56b4f9485a5b3b21e66b2f4f91a0d54a1411ee4fd5e680772a2f7a35638d37d3',
133+
protocolFee: 5110000000000000.0,
134+
protocolVersion: 3,
135+
quoteDate: new Date('2020-10-05T19:10:35.000Z'),
136+
senderAddress: '0x0000008155f9986614d6fcba5388b624023bcb77',
137+
taker: '0xf9757222770d93f0f71c30098d12d4754209f4d4',
138+
transactionHash:
139+
'0xd1e01c31a2183107221ef094b3f7cbfedd13db0340df935464c1dddd2259a1ea',
140+
type: 0,
141+
apps: [],
142+
relayerId: 35,
143+
conversions: {
144+
USD: {
145+
amount: 4905.859567,
146+
protocolFee: 1.7990777,
147+
},
148+
},
149+
pricingStatus: 0,
150+
});
151+
152+
let indexingBody;
153+
elasticsearchMock.add(
154+
{
155+
method: 'PUT',
156+
path: '/fills/_doc/5f7b709a5a345268dec8d425',
157+
},
158+
({ body }) => {
159+
indexingBody = body;
160+
161+
return { status: 'ok' };
162+
},
163+
);
164+
165+
await consumer.fn(
166+
{ data: { fillId: '5f7b709a5a345268dec8d425' } },
167+
mockOptions,
168+
);
169+
170+
expect(indexingBody).toEqual({
171+
apps: [],
172+
assets: [
173+
{
174+
bridgeAddress: '0xc47b7094f378e54347e281aab170e8cca69d880a',
175+
tokenAddress: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984',
176+
},
177+
{ tokenAddress: '0x6b175474e89094c44da98b954eedeac495271d0f' },
178+
],
179+
date: '2020-10-05T19:10:18.000Z',
180+
feeRecipient: '0x1000000000000000000000000000000000000011',
181+
fees: [],
182+
maker: '0xc47b7094f378e54347e281aab170e8cca69d880a',
183+
orderHash:
184+
'0x56b4f9485a5b3b21e66b2f4f91a0d54a1411ee4fd5e680772a2f7a35638d37d3',
185+
protocolFeeETH: 5110000000000000,
186+
protocolFeeUSD: 1.7990777,
187+
protocolVersion: 3,
188+
relayerId: 35,
189+
senderAddress: '0x0000008155f9986614d6fcba5388b624023bcb77',
190+
status: 1,
191+
taker: '0xf9757222770d93f0f71c30098d12d4754209f4d4',
192+
tradeCountContribution: 1,
193+
tradeVolume: 4905.859567,
194+
traders: [
195+
'0xc47b7094f378e54347e281aab170e8cca69d880a',
196+
'0xf9757222770d93f0f71c30098d12d4754209f4d4',
197+
],
198+
transactionHash:
199+
'0xd1e01c31a2183107221ef094b3f7cbfedd13db0340df935464c1dddd2259a1ea',
200+
updatedAt: '2020-08-02T08:42:24.934Z',
201+
value: 4905.859567,
202+
});
203+
});
204+
205+
it('should index transaction sender as taker when fill taker is contract address', async () => {
206+
const AddressMetadata = getModel('AddressMetadata');
207+
const Fill = getModel('Fill');
208+
const Transaction = getModel('Transaction');
209+
210+
await AddressMetadata.create({
211+
address: '0xd4690a51044db77d91d7aa8f7a3a5ad5da331af0',
212+
isContract: true,
213+
});
214+
215+
await Fill.create({
216+
_id: '5f7556972d14a83036966e50',
217+
hasValue: true,
218+
immeasurable: false,
219+
status: 1,
220+
assets: [
221+
{
222+
tokenResolved: true,
223+
amount: 3.6e17,
224+
tokenAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
225+
actor: 0,
226+
price: {
227+
USD: 362.75,
228+
},
229+
value: {
230+
USD: 130.59,
231+
},
232+
},
233+
{
234+
tokenResolved: true,
235+
amount: 1,
236+
tokenAddress: '0xd4690a51044db77d91d7aa8f7a3a5ad5da331af0',
237+
actor: 1,
238+
price: {
239+
USD: 130.59,
240+
},
241+
value: {
242+
USD: 130.59,
243+
},
244+
},
245+
],
246+
blockHash:
247+
'0x564e844ba7f689212cee46dc58cd35f14307a3949b92688e1453bd591bdeeedb',
248+
blockNumber: 10967948,
249+
date: new Date('2020-10-01T04:06:04.000Z'),
250+
eventId: '5f7556972d14a83036966e50',
251+
fees: [
252+
{
253+
amount: {
254+
token: 9000000000000000.0,
255+
USD: 3.26475,
256+
},
257+
tokenAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
258+
traderType: 0,
259+
},
260+
],
261+
feeRecipient: '0x0d056bb17ad4df5593b93a1efc29cb35ba4aa38d',
262+
logIndex: 188,
263+
maker: '0x74f90dbb59e9b8c4dfa0601cd303cb11e9fa4a78',
264+
orderHash:
265+
'0xe09c34f20581e253583105d33461dcc9a3e953d7420af9fceb740ce9ebc3a3d9',
266+
protocolFee: 4711000000000000.0,
267+
protocolVersion: 3,
268+
senderAddress: '0xd4690a51044db77d91d7aa8f7a3a5ad5da331af0',
269+
taker: '0xd4690a51044db77d91d7aa8f7a3a5ad5da331af0',
270+
transactionHash:
271+
'0x8222bab3a43ebacc13df998bacedc36abf43da9462726fbec28c778ce981395a',
272+
type: 0,
273+
apps: [],
274+
relayerId: 28,
275+
conversions: {
276+
USD: {
277+
protocolFee: 1.70891525,
278+
amount: 130.59,
279+
},
280+
},
281+
pricingStatus: 0,
282+
});
283+
284+
await Transaction.create({
285+
_id: '5f75569f6ee6272c398548bf',
286+
blockHash:
287+
'0x564e844ba7f689212cee46dc58cd35f14307a3949b92688e1453bd591bdeeedb',
288+
blockNumber: 10967948,
289+
data:
290+
'0xa2b18d9500000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000005c09694a40200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000277ef970000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000074f90dbb59e9b8c4dfa0601cd303cb11e9fa4a7800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d056bb17ad4df5593b93a1efc29cb35ba4aa38d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004fefa17b72400000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001ff973cafa80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f7d97960000000000000000000000000000000000000000000000000000017468195e9e00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000001c4a7cb5fb7000000000000000000000000d4690a51044db77d91d7aa8f7a3a5ad5da331af0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000e3a2a1f2146d86a604adc220b4967a898d7fe0700000000000000000000000009a379ef7218bcfd8913faa8b281ebc5a2e0bc0400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000421c4af7c6158183c2e4f2468535f94b64910780bae3be8dba8e86bece0b528db1c941d0f12f3c55184cc6a3484484e9d2ab8a82f1290fb864f3c6972eaf5f9311a4020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
291+
date: new Date('2020-10-01T04:06:04.000Z'),
292+
from: '0x819dbfd8788e44917de930252dc1474a066ea2b7',
293+
gasLimit: 567385,
294+
gasPrice: '67300000000',
295+
gasUsed: 366120,
296+
hash:
297+
'0x8222bab3a43ebacc13df998bacedc36abf43da9462726fbec28c778ce981395a',
298+
index: 74,
299+
nonce: '1477',
300+
to: '0xd4690a51044db77d91d7aa8f7a3a5ad5da331af0',
301+
value: '10095000000000000',
302+
});
303+
304+
let indexingBody;
305+
elasticsearchMock.add(
306+
{
307+
method: 'PUT',
308+
path: '/fills/_doc/5f7556972d14a83036966e50',
309+
},
310+
({ body }) => {
311+
indexingBody = body;
312+
313+
return { status: 'ok' };
314+
},
315+
);
316+
317+
await consumer.fn(
318+
{ data: { fillId: '5f7556972d14a83036966e50' } },
319+
mockOptions,
320+
);
321+
322+
expect(indexingBody.taker).toBe(
323+
'0x819dbfd8788e44917de930252dc1474a066ea2b7',
324+
);
325+
});
326+
});

src/index/fills/create-document.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const createDocument = fill => {
5050
relayerId: fill.relayerId,
5151
senderAddress: fill.senderAddress,
5252
status: fill.status,
53-
taker: fill.taker,
53+
taker: fill.takerMetadata.isContract ? fill.transaction.from : fill.taker,
5454
transactionHash: fill.transactionHash,
5555
updatedAt: new Date(Date.now()).toISOString(),
5656
value: value === null ? undefined : value,

0 commit comments

Comments
 (0)