@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.
@@ -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, getCachedMarketMakers } =
58
- config.rateConfig;
68
+ const { filterMarketMakers } = config.rateConfig;
59
69
 
60
- const cachedMarketMakers = (await getCachedMarketMakers()) || [];
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.marketMakersFetcher.startPolling();
93
- this.rateFetcher.startPolling();
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.rawset(
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;
@@ -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
  }