@paraswap/dex-lib 4.1.7-pub-sub.3 → 4.1.7-pub-sub.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/dex/dexalot/dexalot.d.ts +2 -9
- package/build/dex/dexalot/dexalot.js +18 -62
- package/build/dex/dexalot/dexalot.js.map +1 -1
- package/build/dex/dexalot/rate-fetcher.d.ts +19 -4
- package/build/dex/dexalot/rate-fetcher.js +112 -8
- package/build/dex/dexalot/rate-fetcher.js.map +1 -1
- package/build/dex/dexalot/types.d.ts +0 -1
- package/build/dex/generic-rfq/rate-fetcher.js +0 -12
- package/build/dex/generic-rfq/rate-fetcher.js.map +1 -1
- package/build/dex/hashflow/constants.d.ts +2 -2
- package/build/dex/hashflow/constants.js +2 -2
- package/build/dex/hashflow/hashflow.d.ts +1 -6
- package/build/dex/hashflow/hashflow.js +9 -34
- package/build/dex/hashflow/hashflow.js.map +1 -1
- package/build/dex/hashflow/rate-fetcher.d.ts +12 -2
- package/build/dex/hashflow/rate-fetcher.js +54 -6
- package/build/dex/hashflow/rate-fetcher.js.map +1 -1
- package/build/dex/hashflow/types.d.ts +0 -1
- package/build/lib/pub-sub.d.ts +0 -2
- package/build/lib/pub-sub.js +0 -12
- package/build/lib/pub-sub.js.map +1 -1
- package/package.json +1 -1
- package/src/dex/dexalot/dexalot.ts +27 -127
- package/src/dex/dexalot/rate-fetcher.ts +219 -9
- package/src/dex/dexalot/types.ts +0 -1
- package/src/dex/generic-rfq/rate-fetcher.ts +0 -30
- package/src/dex/hashflow/constants.ts +2 -2
- package/src/dex/hashflow/hashflow.ts +11 -67
- package/src/dex/hashflow/rate-fetcher.ts +106 -8
- package/src/dex/hashflow/types.ts +0 -1
- package/src/lib/pub-sub.ts +0 -27
|
@@ -1,17 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MarketMakersResponse,
|
|
3
|
+
PriceLevelsResponse,
|
|
4
|
+
} from '@hashflow/taker-js/dist/types/rest';
|
|
1
5
|
import { Network } from '../../constants';
|
|
2
6
|
import { IDexHelper } from '../../dex-helper';
|
|
3
7
|
import { Fetcher, SkippingRequest } from '../../lib/fetcher/fetcher';
|
|
4
8
|
import { validateAndCast } from '../../lib/validators';
|
|
5
|
-
import { Logger } from '../../types';
|
|
9
|
+
import { Address, Logger } from '../../types';
|
|
6
10
|
import {
|
|
7
11
|
HashflowMarketMakersResponse,
|
|
8
12
|
HashflowRateFetcherConfig,
|
|
9
13
|
HashflowRatesResponse,
|
|
10
14
|
} from './types';
|
|
11
15
|
import { marketMakersValidator, pricesResponseValidator } from './validators';
|
|
16
|
+
import { HASHFLOW_BLACKLIST_TTL_S } from './constants';
|
|
17
|
+
import { ExpKeyValuePubSub, NonExpSetPubSub } from '../../lib/pub-sub';
|
|
12
18
|
|
|
13
19
|
export class RateFetcher {
|
|
14
20
|
private rateFetcher: Fetcher<HashflowRatesResponse>;
|
|
21
|
+
private ratePubSub: ExpKeyValuePubSub;
|
|
15
22
|
private pricesCacheKey: string;
|
|
16
23
|
private pricesCacheTTL: number;
|
|
17
24
|
|
|
@@ -19,6 +26,8 @@ export class RateFetcher {
|
|
|
19
26
|
private marketMakersCacheKey: string;
|
|
20
27
|
private marketMakersCacheTTL: number;
|
|
21
28
|
|
|
29
|
+
private blacklistedPubSub: NonExpSetPubSub;
|
|
30
|
+
|
|
22
31
|
constructor(
|
|
23
32
|
private dexHelper: IDexHelper,
|
|
24
33
|
private dexKey: string,
|
|
@@ -48,16 +57,18 @@ export class RateFetcher {
|
|
|
48
57
|
logger,
|
|
49
58
|
);
|
|
50
59
|
|
|
60
|
+
this.ratePubSub = new ExpKeyValuePubSub(dexHelper, dexKey, 'rates');
|
|
61
|
+
|
|
51
62
|
this.rateFetcher = new Fetcher<HashflowRatesResponse>(
|
|
52
63
|
dexHelper.httpRequest,
|
|
53
64
|
{
|
|
54
65
|
info: {
|
|
55
66
|
requestOptions: config.rateConfig.pricesReqParams,
|
|
56
67
|
requestFunc: async options => {
|
|
57
|
-
const { filterMarketMakers
|
|
58
|
-
config.rateConfig;
|
|
68
|
+
const { filterMarketMakers } = config.rateConfig;
|
|
59
69
|
|
|
60
|
-
const cachedMarketMakers =
|
|
70
|
+
const cachedMarketMakers =
|
|
71
|
+
(await this.getCachedMarketMakers()) || [];
|
|
61
72
|
const filteredMarketMakers = await filterMarketMakers(
|
|
62
73
|
cachedMarketMakers,
|
|
63
74
|
);
|
|
@@ -86,11 +97,24 @@ export class RateFetcher {
|
|
|
86
97
|
config.rateConfig.pricesIntervalMs,
|
|
87
98
|
logger,
|
|
88
99
|
);
|
|
100
|
+
|
|
101
|
+
this.blacklistedPubSub = new NonExpSetPubSub(
|
|
102
|
+
dexHelper,
|
|
103
|
+
dexKey,
|
|
104
|
+
'blacklisted',
|
|
105
|
+
);
|
|
89
106
|
}
|
|
90
107
|
|
|
91
|
-
start() {
|
|
92
|
-
this.
|
|
93
|
-
|
|
108
|
+
async start() {
|
|
109
|
+
if (!this.dexHelper.config.isSlave) {
|
|
110
|
+
this.marketMakersFetcher.startPolling();
|
|
111
|
+
this.rateFetcher.startPolling();
|
|
112
|
+
} else {
|
|
113
|
+
this.ratePubSub.subscribe();
|
|
114
|
+
|
|
115
|
+
const allBlacklisted = await this.getAllBlacklisted();
|
|
116
|
+
this.blacklistedPubSub.initializeAndSubscribe(allBlacklisted);
|
|
117
|
+
}
|
|
94
118
|
}
|
|
95
119
|
|
|
96
120
|
stop() {
|
|
@@ -109,10 +133,84 @@ export class RateFetcher {
|
|
|
109
133
|
|
|
110
134
|
private handleRatesResponse(resp: HashflowRatesResponse): void {
|
|
111
135
|
const { levels } = resp;
|
|
112
|
-
this.dexHelper.cache.
|
|
136
|
+
this.dexHelper.cache.setex(
|
|
137
|
+
this.dexKey,
|
|
138
|
+
this.network,
|
|
113
139
|
this.pricesCacheKey,
|
|
140
|
+
this.pricesCacheTTL,
|
|
114
141
|
JSON.stringify(levels),
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
this.ratePubSub.publish(
|
|
145
|
+
{ [this.pricesCacheKey]: levels },
|
|
115
146
|
this.pricesCacheTTL,
|
|
116
147
|
);
|
|
117
148
|
}
|
|
149
|
+
|
|
150
|
+
async getCachedMarketMakers(): Promise<
|
|
151
|
+
MarketMakersResponse['marketMakers'] | null
|
|
152
|
+
> {
|
|
153
|
+
const cachedMarketMakers = await this.dexHelper.cache.rawget(
|
|
154
|
+
this.marketMakersCacheKey,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
if (cachedMarketMakers) {
|
|
158
|
+
return JSON.parse(
|
|
159
|
+
cachedMarketMakers,
|
|
160
|
+
) as MarketMakersResponse['marketMakers'];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async getCachedLevels(): Promise<PriceLevelsResponse['levels'] | null> {
|
|
167
|
+
const cachedLevels = await this.ratePubSub.getAndCache(this.pricesCacheKey);
|
|
168
|
+
|
|
169
|
+
if (cachedLevels) {
|
|
170
|
+
return cachedLevels as PriceLevelsResponse['levels'];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async isBlacklisted(txOrigin: Address): Promise<boolean> {
|
|
177
|
+
return this.blacklistedPubSub.has(txOrigin.toLowerCase());
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async setBlacklist(
|
|
181
|
+
txOrigin: Address,
|
|
182
|
+
ttl: number = HASHFLOW_BLACKLIST_TTL_S,
|
|
183
|
+
) {
|
|
184
|
+
await this.dexHelper.cache.setex(
|
|
185
|
+
this.dexKey,
|
|
186
|
+
this.network,
|
|
187
|
+
this.getBlackListKey(txOrigin),
|
|
188
|
+
ttl,
|
|
189
|
+
'blacklisted',
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
this.blacklistedPubSub.publish([txOrigin.toLowerCase()]);
|
|
193
|
+
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async getAllBlacklisted(): Promise<Address[]> {
|
|
198
|
+
const defaultKey = this.getBlackListKey('');
|
|
199
|
+
const pattern = `${defaultKey}*`;
|
|
200
|
+
const allBlacklisted = await this.dexHelper.cache.keys(
|
|
201
|
+
this.dexKey,
|
|
202
|
+
this.network,
|
|
203
|
+
pattern,
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
return allBlacklisted.map(t => this.getAddressFromBlackListKey(t));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
getBlackListKey(address: Address) {
|
|
210
|
+
return `blacklist_${address}`.toLowerCase();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
getAddressFromBlackListKey(key: Address) {
|
|
214
|
+
return (key.split('blacklist_')[1] ?? '').toLowerCase();
|
|
215
|
+
}
|
|
118
216
|
}
|
|
@@ -64,7 +64,6 @@ export type HashflowRateFetcherConfig = {
|
|
|
64
64
|
};
|
|
65
65
|
pricesIntervalMs: number;
|
|
66
66
|
markerMakersIntervalMs: number;
|
|
67
|
-
getCachedMarketMakers: () => Promise<string[] | null>;
|
|
68
67
|
filterMarketMakers: (makers: string[]) => Promise<string[]>;
|
|
69
68
|
pricesCacheKey: string;
|
|
70
69
|
marketMakersCacheKey: string;
|
package/src/lib/pub-sub.ts
CHANGED
|
@@ -15,7 +15,6 @@ export class ExpKeyValuePubSub {
|
|
|
15
15
|
channel: string;
|
|
16
16
|
network: Network;
|
|
17
17
|
localCache: NodeCache = new NodeCache();
|
|
18
|
-
logPrefix = 'ExpKeyValuePubSub';
|
|
19
18
|
|
|
20
19
|
logger: Logger;
|
|
21
20
|
|
|
@@ -37,21 +36,12 @@ export class ExpKeyValuePubSub {
|
|
|
37
36
|
|
|
38
37
|
this.dexHelper.cache.subscribe(this.channel, (_, msg) => {
|
|
39
38
|
const decodedMsg = JSON.parse(msg) as KeyValuePubSubMsg;
|
|
40
|
-
this.logger.info(
|
|
41
|
-
`${this.logPrefix} Received msg: '${Object.keys(decodedMsg).length}'`,
|
|
42
|
-
);
|
|
43
39
|
this.handleSubscription(decodedMsg);
|
|
44
40
|
});
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
publish(data: Record<string, unknown>, ttl: number) {
|
|
48
44
|
const expiresAt = Math.round(Date.now() / 1000) + ttl;
|
|
49
|
-
this.logger.info(
|
|
50
|
-
`${this.logPrefix} Publishing msg: '${JSON.stringify({
|
|
51
|
-
expiresAt,
|
|
52
|
-
data: Object.keys(data).length,
|
|
53
|
-
})}'`,
|
|
54
|
-
);
|
|
55
45
|
this.dexHelper.cache.publish(
|
|
56
46
|
this.channel,
|
|
57
47
|
JSON.stringify({ expiresAt, data }),
|
|
@@ -83,12 +73,6 @@ export class ExpKeyValuePubSub {
|
|
|
83
73
|
async getAndCache<T>(key: string): Promise<T | null> {
|
|
84
74
|
const localValue = this.localCache.get<T>(key);
|
|
85
75
|
|
|
86
|
-
this.logger.info(
|
|
87
|
-
`${this.logPrefix} Getting and caching key: ${key}, localValue length: ${
|
|
88
|
-
localValue ? Object.keys(localValue).length : 0
|
|
89
|
-
}`,
|
|
90
|
-
);
|
|
91
|
-
|
|
92
76
|
if (localValue) {
|
|
93
77
|
return localValue;
|
|
94
78
|
}
|
|
@@ -280,7 +264,6 @@ export class NonExpSetPubSub {
|
|
|
280
264
|
channel: string;
|
|
281
265
|
network: Network;
|
|
282
266
|
set = new Set<string>();
|
|
283
|
-
logPrefix = 'NonExpSetPubSub';
|
|
284
267
|
|
|
285
268
|
logger: Logger;
|
|
286
269
|
|
|
@@ -296,10 +279,6 @@ export class NonExpSetPubSub {
|
|
|
296
279
|
}
|
|
297
280
|
|
|
298
281
|
async initializeAndSubscribe(initialSet: string[]) {
|
|
299
|
-
this.logger.info(
|
|
300
|
-
`${this.logPrefix} initializeAndSubscribe with ${initialSet}`,
|
|
301
|
-
);
|
|
302
|
-
|
|
303
282
|
for (const member of initialSet) {
|
|
304
283
|
this.set.add(member);
|
|
305
284
|
}
|
|
@@ -312,23 +291,17 @@ export class NonExpSetPubSub {
|
|
|
312
291
|
|
|
313
292
|
this.dexHelper.cache.subscribe(this.channel, (_, msg) => {
|
|
314
293
|
const decodedMsg = JSON.parse(msg) as SetPubSubMsg;
|
|
315
|
-
this.logger.info(
|
|
316
|
-
`${this.logPrefix} Received subscription msg: '${decodedMsg.length}'`,
|
|
317
|
-
);
|
|
318
294
|
this.handleSubscription(decodedMsg);
|
|
319
295
|
});
|
|
320
296
|
}
|
|
321
297
|
|
|
322
298
|
publish(msg: SetPubSubMsg) {
|
|
323
299
|
if (msg.length > 0) {
|
|
324
|
-
this.logger.info(`${this.logPrefix} Publishing msg: '${msg.length}'`);
|
|
325
300
|
this.dexHelper.cache.publish(this.channel, JSON.stringify(msg));
|
|
326
301
|
}
|
|
327
302
|
}
|
|
328
303
|
|
|
329
304
|
handleSubscription(set: SetPubSubMsg) {
|
|
330
|
-
this.logger.info(`${this.logPrefix} Received subscription msg: '${set}'`);
|
|
331
|
-
|
|
332
305
|
for (const key of set) {
|
|
333
306
|
this.set.add(key);
|
|
334
307
|
}
|