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

Commit efc7c2c

Browse files
authored
Traders endpoints improvements (#426)
* Update trader stats endpoint to use trader_fills index * Update trader metrics endpoint to use trader_fills endpoint * Update active trader metrics endpoint to use trader_fills index * Migrate trader lookup endpoint to trader_fills endpoint * Update relayer endpoint to pull trader count from new index * Update relayer metrics to use trader_fills * Update relayers endpoint to use trader_fills * Update fill endpoints to return correct taker * Migrate traders endpoint to trader_fills index
1 parent 4092d42 commit efc7c2c

17 files changed

+850
-456
lines changed

src/app/routes/v1/fills.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ const createRouter = () => {
152152
{ path: 'assets.token', select: 'decimals name symbol type' },
153153
{ path: 'fees.token', select: 'decimals name symbol type' },
154154
{ path: 'affiliate', select: 'name imageUrl' },
155+
{ path: 'takerMetadata', select: 'isContract' },
156+
{ path: 'transaction', select: 'from' },
155157
],
156158
})
157159
: null;

src/app/routes/v1/traders.js

Lines changed: 11 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,10 @@ const Router = require('koa-router');
44
const { TIME_PERIOD } = require('../../../constants');
55
const AddressMetadata = require('../../../model/address-metadata');
66
const getDatesForTimePeriod = require('../../../util/get-dates-for-time-period');
7-
const getTradersWith24HourStats = require('../../../traders/get-traders-with-24-hour-stats');
87
const getTradersWithStatsForDates = require('../../../traders/get-traders-with-stats-for-dates');
98
const InvalidParameterError = require('../../errors/invalid-parameter-error');
109
const middleware = require('../../middleware');
1110

12-
const parseBooleanString = value => {
13-
if (value === 'true') {
14-
return true;
15-
}
16-
17-
if (value === 'false') {
18-
return false;
19-
}
20-
21-
return undefined;
22-
};
23-
24-
const VALID_SORT_VALUES = [
25-
'fillVolume.maker',
26-
'fillVolume.taker',
27-
'fillVolume.total',
28-
];
29-
3011
const createRouter = () => {
3112
const router = new Router();
3213

@@ -39,7 +20,7 @@ const createRouter = () => {
3920
}),
4021
middleware.timePeriod('statsPeriod', TIME_PERIOD.DAY),
4122
async ({ pagination, params, request, response }, next) => {
42-
const { excludeRelayers, sortBy, type } = request.query;
23+
const { excludeRelayers, type } = request.query;
4324

4425
if (type !== undefined && type !== 'maker' && type !== 'taker') {
4526
throw new InvalidParameterError(
@@ -59,32 +40,19 @@ const createRouter = () => {
5940
);
6041
}
6142

62-
if (sortBy !== undefined && !VALID_SORT_VALUES.includes(sortBy)) {
63-
throw new InvalidParameterError(
64-
`Must be one of: ${VALID_SORT_VALUES.join(', ')}`,
65-
'Invalid query parameter: sortBy',
66-
);
67-
}
68-
6943
const { limit, page } = pagination;
7044
const { statsPeriod } = params;
7145
const { dateFrom, dateTo } = getDatesForTimePeriod(statsPeriod);
72-
const { traders, resultCount } =
73-
statsPeriod === TIME_PERIOD.DAY
74-
? await getTradersWith24HourStats({
75-
excludeRelayers: parseBooleanString(excludeRelayers),
76-
page,
77-
limit,
78-
sortBy,
79-
type,
80-
})
81-
: await getTradersWithStatsForDates(dateFrom, dateTo, {
82-
excludeRelayers,
83-
page,
84-
limit,
85-
sortBy,
86-
type,
87-
});
46+
const { traders, resultCount } = await getTradersWithStatsForDates(
47+
dateFrom,
48+
dateTo,
49+
{
50+
excludeRelayers,
51+
page,
52+
limit,
53+
type,
54+
},
55+
);
8856

8957
const addresses = traders.map(trader => trader.address);
9058

src/app/routes/v1/util/transform-fill.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ const transformFill = fill => {
1313
const assets = getAssetsForFill(fill);
1414
const fees = getFeesForFill(fill);
1515
const conversions = _.get(fill, `conversions.USD`);
16+
const taker = _.get(fill, 'takerMetadata.isContract', false)
17+
? _.get(fill, 'transaction.from', fill.taker)
18+
: fill.taker;
1619

1720
const protocolFee =
1821
fill.protocolFee !== undefined
@@ -42,7 +45,7 @@ const transformFill = fill => {
4245
relayer: formatRelayer(fill.relayer),
4346
senderAddress: fill.senderAddress,
4447
status: formatFillStatus(fill.status),
45-
takerAddress: fill.taker,
48+
takerAddress: taker,
4649
transactionHash: fill.transactionHash,
4750
value: _.has(conversions, 'amount')
4851
? {

src/app/routes/v1/util/transform-fills.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ const transformRelayer = relayer =>
1111
const transformFill = fill => {
1212
const assets = getAssetsForFill(fill);
1313
const conversions = _.get(fill, `conversions.USD`);
14+
const taker = _.get(fill, 'takerMetadata.isContract', false)
15+
? _.get(fill, 'transaction.from', fill.taker)
16+
: fill.taker;
1417

1518
const protocolFee =
1619
fill.protocolFee !== undefined
@@ -30,7 +33,7 @@ const transformFill = fill => {
3033
protocolVersion: fill.protocolVersion,
3134
relayer: transformRelayer(fill.relayer),
3235
status: formatFillStatus(fill.status),
33-
takerAddress: fill.taker,
36+
takerAddress: taker,
3437
value: _.has(conversions, 'amount')
3538
? {
3639
USD: _.get(conversions, 'amount'),

src/fills/search-fills.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ const searchFills = async (params, options) => {
2121
.populate([
2222
{ path: 'relayer', select: 'imageUrl name slug' },
2323
{ path: 'assets.token', select: 'decimals name symbol type imageUrl' },
24-
{ path: 'fees.token', select: 'decimals name symbol type' },
24+
{ path: 'transaction', select: 'from' },
25+
{ path: 'takerMetadata', select: 'isContract' },
2526
])
2627
.sort({ date: -1 });
2728

src/metrics/get-relayer-metrics.js

Lines changed: 88 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,72 @@
11
const elasticsearch = require('../util/elasticsearch');
22
const getDatesForMetrics = require('../util/get-dates-for-metrics');
33

4-
const getRelayerMetrics = async (relayerId, period, granularity) => {
5-
const { dateFrom, dateTo } = getDatesForMetrics(period, granularity);
4+
const getQuery = (relayerId, dateFrom, dateTo) => {
5+
return {
6+
bool: {
7+
filter: [
8+
{
9+
range: {
10+
date: {
11+
gte: dateFrom,
12+
lte: dateTo,
13+
},
14+
},
15+
},
16+
relayerId !== null
17+
? {
18+
term: {
19+
relayerId,
20+
},
21+
}
22+
: undefined,
23+
].filter(x => x !== undefined),
24+
must_not: [
25+
relayerId === null
26+
? {
27+
exists: {
28+
field: 'relayerId',
29+
},
30+
}
31+
: undefined,
32+
].filter(x => x !== undefined),
33+
},
34+
};
35+
};
636

37+
const getTraderMetrics = async (relayerId, dateFrom, dateTo, granularity) => {
38+
const results = await elasticsearch.getClient().search({
39+
index: 'trader_fills',
40+
body: {
41+
aggs: {
42+
metrics_by_date: {
43+
date_histogram: {
44+
field: 'date',
45+
calendar_interval: granularity,
46+
extended_bounds: {
47+
min: dateFrom,
48+
max: dateTo,
49+
},
50+
},
51+
aggs: {
52+
traderCount: {
53+
cardinality: { field: 'address' },
54+
},
55+
},
56+
},
57+
},
58+
size: 0,
59+
query: getQuery(relayerId, dateFrom, dateTo),
60+
},
61+
});
62+
63+
return results.body.aggregations.metrics_by_date.buckets.map(x => ({
64+
date: new Date(x.key_as_string),
65+
traderCount: x.traderCount.value,
66+
}));
67+
};
68+
69+
const getBasicMetrics = async (relayerId, dateFrom, dateTo, granularity) => {
770
const results = await elasticsearch.getClient().search({
871
index: 'fills',
972
body: {
@@ -27,43 +90,11 @@ const getRelayerMetrics = async (relayerId, period, granularity) => {
2790
tradeVolume: {
2891
sum: { field: 'tradeVolume' },
2992
},
30-
traderCount: {
31-
cardinality: { field: 'traders' },
32-
},
3393
},
3494
},
3595
},
3696
size: 0,
37-
query: {
38-
bool: {
39-
filter: [
40-
{
41-
range: {
42-
date: {
43-
gte: dateFrom,
44-
lte: dateTo,
45-
},
46-
},
47-
},
48-
relayerId !== null
49-
? {
50-
term: {
51-
relayerId,
52-
},
53-
}
54-
: undefined,
55-
].filter(x => x !== undefined),
56-
must_not: [
57-
relayerId === null
58-
? {
59-
exists: {
60-
field: 'relayerId',
61-
},
62-
}
63-
: undefined,
64-
].filter(x => x !== undefined),
65-
},
66-
},
97+
query: getQuery(relayerId, dateFrom, dateTo),
6798
},
6899
});
69100

@@ -73,8 +104,29 @@ const getRelayerMetrics = async (relayerId, period, granularity) => {
73104
fillVolume: x.fillVolume.value,
74105
tradeCount: relayerId === null ? x.doc_count : x.tradeCount.value,
75106
tradeVolume: relayerId === null ? x.fillVolume.value : x.tradeVolume.value,
76-
traderCount: x.traderCount.value,
77107
}));
78108
};
79109

110+
const getRelayerMetrics = async (relayerId, period, granularity) => {
111+
const { dateFrom, dateTo } = getDatesForMetrics(period, granularity);
112+
113+
const [basicMetrics, traderMetrics] = await Promise.all([
114+
getBasicMetrics(relayerId, dateFrom, dateTo, granularity),
115+
getTraderMetrics(relayerId, dateFrom, dateTo, granularity),
116+
]);
117+
118+
const combinedMetrics = basicMetrics.map(basicMetric => {
119+
const traderMetric = traderMetrics.find(
120+
tm => tm.date.toISOString() === basicMetric.date.toISOString(),
121+
);
122+
123+
return {
124+
...basicMetric,
125+
traderCount: traderMetric.traderCount,
126+
};
127+
});
128+
129+
return combinedMetrics;
130+
};
131+
80132
module.exports = getRelayerMetrics;

src/model/address-metadata.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const mongoose = require('mongoose');
33
const schema = mongoose.Schema({
44
address: String,
55
imageUrl: String,
6+
isContract: Boolean,
67
name: String,
78
});
89

src/model/address-metric.js

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/model/fill.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const { FILL_STATUS } = require('../constants');
44

55
const { Schema } = mongoose;
66

7+
require('./transaction');
8+
79
const schema = Schema({
810
affiliateAddress: String,
911
assets: [
@@ -77,6 +79,20 @@ schema.virtual('affiliate', {
7779
justOne: true,
7880
});
7981

82+
schema.virtual('takerMetadata', {
83+
ref: 'AddressMetadata',
84+
localField: 'taker',
85+
foreignField: 'address',
86+
justOne: true,
87+
});
88+
89+
schema.virtual('transaction', {
90+
ref: 'Transaction',
91+
localField: 'transactionHash',
92+
foreignField: 'hash',
93+
justOne: true,
94+
});
95+
8096
const Model = mongoose.model('Fill', schema);
8197

8298
module.exports = Model;

src/model/transaction.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const mongoose = require('mongoose');
2+
3+
const { Schema } = mongoose;
4+
5+
const schema = Schema({
6+
affiliateAddress: String,
7+
blockHash: String,
8+
blockNumber: Number,
9+
data: String,
10+
date: Date,
11+
from: String,
12+
gasLimit: Number,
13+
gasPrice: String,
14+
gasUsed: Number,
15+
hash: String,
16+
index: Number,
17+
nonce: String,
18+
quoteDate: Date,
19+
to: String,
20+
value: String,
21+
});
22+
23+
const Transaction = mongoose.model('Transaction', schema);
24+
25+
module.exports = Transaction;

0 commit comments

Comments
 (0)