@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.
@@ -2,9 +2,11 @@ import { Network } from '../../constants';
2
2
  import { IDexHelper } from '../../dex-helper';
3
3
  import { Fetcher } from '../../lib/fetcher/fetcher';
4
4
  import { validateAndCast } from '../../lib/validators';
5
- import { Logger, Token } from '../../types';
5
+ import { Address, Logger, Token } from '../../types';
6
6
  import {
7
7
  DexalotBlacklistResponse,
8
+ TokenDataMap,
9
+ TokenAddrDataMap,
8
10
  DexalotPairsResponse,
9
11
  DexalotPricesResponse,
10
12
  DexalotRateFetcherConfig,
@@ -16,13 +18,21 @@ import {
16
18
  pairsResponseValidator,
17
19
  pricesResponseValidator,
18
20
  } from './validators';
21
+ import {
22
+ DEXALOT_BLACKLIST_CACHES_TTL_S,
23
+ DEXALOT_RATE_LIMITED_TTL_S,
24
+ DEXALOT_RATELIMIT_CACHE_VALUE,
25
+ DEXALOT_RESTRICT_TTL_S,
26
+ DEXALOT_RESTRICTED_CACHE_KEY,
27
+ } from './constants';
28
+ import { ExpKeyValuePubSub, NonExpSetPubSub } from '../../lib/pub-sub';
19
29
 
20
30
  export class RateFetcher {
21
31
  private pairsFetcher: Fetcher<DexalotPairsResponse>;
22
32
  private pairsCacheKey: string;
23
- private pairsCacheTTL: number;
24
33
 
25
34
  private rateFetcher: Fetcher<DexalotPricesResponse>;
35
+ private rateTokensPubSub: ExpKeyValuePubSub;
26
36
  private pricesCacheKey: string;
27
37
  private pricesCacheTTL: number;
28
38
 
@@ -31,9 +41,12 @@ export class RateFetcher {
31
41
  private tokensCacheTTL: number;
32
42
 
33
43
  private blacklistFetcher: Fetcher<DexalotBlacklistResponse>;
44
+ private blacklistPubSub: NonExpSetPubSub;
34
45
  private blacklistCacheKey: string;
35
46
  private blacklistCacheTTL: number;
36
47
 
48
+ private restrictedPoolPubSub: ExpKeyValuePubSub;
49
+
37
50
  constructor(
38
51
  private dexHelper: IDexHelper,
39
52
  private dexKey: string,
@@ -42,7 +55,6 @@ export class RateFetcher {
42
55
  config: DexalotRateFetcherConfig,
43
56
  ) {
44
57
  this.pairsCacheKey = config.rateConfig.pairsCacheKey;
45
- this.pairsCacheTTL = config.rateConfig.pairsCacheTTLSecs;
46
58
  this.pricesCacheKey = config.rateConfig.pricesCacheKey;
47
59
  this.pricesCacheTTL = config.rateConfig.pricesCacheTTLSecs;
48
60
  this.tokensAddrCacheKey = config.rateConfig.tokensAddrCacheKey;
@@ -51,6 +63,12 @@ export class RateFetcher {
51
63
  this.blacklistCacheKey = config.rateConfig.blacklistCacheKey;
52
64
  this.blacklistCacheTTL = config.rateConfig.blacklistCacheTTLSecs;
53
65
 
66
+ this.rateTokensPubSub = new ExpKeyValuePubSub(
67
+ dexHelper,
68
+ dexKey,
69
+ 'rateTokens',
70
+ );
71
+
54
72
  this.pairsFetcher = new Fetcher<DexalotPairsResponse>(
55
73
  dexHelper.httpRequest,
56
74
  {
@@ -87,6 +105,7 @@ export class RateFetcher {
87
105
  logger,
88
106
  );
89
107
 
108
+ this.blacklistPubSub = new NonExpSetPubSub(dexHelper, dexKey, 'blacklist');
90
109
  this.blacklistFetcher = new Fetcher<DexalotBlacklistResponse>(
91
110
  dexHelper.httpRequest,
92
111
  {
@@ -104,12 +123,30 @@ export class RateFetcher {
104
123
  config.rateConfig.blacklistIntervalMs,
105
124
  logger,
106
125
  );
126
+
127
+ this.restrictedPoolPubSub = new ExpKeyValuePubSub(
128
+ dexHelper,
129
+ dexKey,
130
+ 'restricted-pool',
131
+ // using default value, we can lazy load non-restricted pools
132
+ // and restrict them by subscribing to this channel
133
+ 'false',
134
+ DEXALOT_RESTRICT_TTL_S,
135
+ );
107
136
  }
108
137
 
109
- start() {
110
- this.pairsFetcher.startPolling();
111
- this.rateFetcher.startPolling();
112
- this.blacklistFetcher.startPolling();
138
+ async start() {
139
+ if (!this.dexHelper.config.isSlave) {
140
+ this.pairsFetcher.startPolling();
141
+ this.rateFetcher.startPolling();
142
+ this.blacklistFetcher.startPolling();
143
+ } else {
144
+ this.rateTokensPubSub.subscribe();
145
+ this.restrictedPoolPubSub.subscribe();
146
+
147
+ const initSet = await this.getAllBlacklisted();
148
+ this.blacklistPubSub.initializeAndSubscribe(initSet);
149
+ }
113
150
  }
114
151
 
115
152
  stop() {
@@ -145,7 +182,7 @@ export class RateFetcher {
145
182
  this.dexKey,
146
183
  this.network,
147
184
  this.pairsCacheKey,
148
- this.pairsCacheTTL,
185
+ this.tokensCacheTTL,
149
186
  JSON.stringify(dexPairs),
150
187
  );
151
188
 
@@ -164,6 +201,15 @@ export class RateFetcher {
164
201
  this.tokensCacheTTL,
165
202
  JSON.stringify(tokenAddrMap),
166
203
  );
204
+
205
+ this.rateTokensPubSub.publish(
206
+ {
207
+ [this.pairsCacheKey]: dexPairs,
208
+ [this.tokensCacheKey]: tokenMap,
209
+ [this.tokensAddrCacheKey]: tokenAddrMap,
210
+ },
211
+ this.tokensCacheTTL,
212
+ );
167
213
  }
168
214
 
169
215
  private handleRatesResponse(resp: DexalotPricesResponse): void {
@@ -180,18 +226,182 @@ export class RateFetcher {
180
226
  this.pricesCacheTTL,
181
227
  JSON.stringify(dexPrices),
182
228
  );
229
+
230
+ this.rateTokensPubSub.publish(
231
+ { [this.pricesCacheKey]: dexPrices },
232
+ this.pricesCacheTTL,
233
+ );
183
234
  }
184
235
 
185
236
  private async handleBlacklistResponse(
186
237
  resp: DexalotBlacklistResponse,
187
238
  ): Promise<void> {
188
239
  const { blacklist } = resp;
240
+ const data = blacklist.map(item => item.toLowerCase());
189
241
  this.dexHelper.cache.setex(
190
242
  this.dexKey,
191
243
  this.network,
192
244
  this.blacklistCacheKey,
193
245
  this.blacklistCacheTTL,
194
- JSON.stringify(blacklist.map(item => item.toLowerCase())),
246
+ JSON.stringify(data),
247
+ );
248
+
249
+ this.blacklistPubSub.publish(data);
250
+ }
251
+
252
+ async getCachedTokens(): Promise<TokenDataMap | null> {
253
+ const cachedTokens = await this.rateTokensPubSub.getAndCache(
254
+ this.tokensCacheKey,
255
+ );
256
+
257
+ if (cachedTokens) {
258
+ return cachedTokens as TokenDataMap;
259
+ }
260
+
261
+ return null;
262
+ }
263
+
264
+ async getCachedPairs(): Promise<PairDataMap | null> {
265
+ const cachedPairs = await this.rateTokensPubSub.getAndCache(
266
+ this.pairsCacheKey,
267
+ );
268
+
269
+ if (cachedPairs) {
270
+ return cachedPairs as PairDataMap;
271
+ }
272
+
273
+ return null;
274
+ }
275
+
276
+ async getCachedTokensAddr(): Promise<TokenAddrDataMap | null> {
277
+ const cachedTokensAddr = await this.rateTokensPubSub.getAndCache(
278
+ this.tokensAddrCacheKey,
279
+ );
280
+
281
+ if (cachedTokensAddr) {
282
+ return cachedTokensAddr as TokenAddrDataMap;
283
+ }
284
+
285
+ return null;
286
+ }
287
+
288
+ async setBlacklist(
289
+ txOrigin: Address,
290
+ ttl: number = DEXALOT_BLACKLIST_CACHES_TTL_S,
291
+ ): Promise<boolean> {
292
+ const blacklist = await this.getAllBlacklisted();
293
+
294
+ blacklist.push(txOrigin.toLowerCase());
295
+
296
+ this.dexHelper.cache.setex(
297
+ this.dexKey,
298
+ this.network,
299
+ this.blacklistCacheKey,
300
+ ttl,
301
+ JSON.stringify(blacklist),
302
+ );
303
+
304
+ this.blacklistPubSub.publish([txOrigin.toLowerCase()]);
305
+
306
+ return true;
307
+ }
308
+
309
+ async getAllBlacklisted(): Promise<string[]> {
310
+ const cachedBlacklist = await this.dexHelper.cache.get(
311
+ this.dexKey,
312
+ this.network,
313
+ this.blacklistCacheKey,
195
314
  );
315
+
316
+ if (cachedBlacklist) {
317
+ return JSON.parse(cachedBlacklist);
318
+ }
319
+
320
+ return [];
321
+ }
322
+
323
+ async isBlacklisted(txOrigin: Address): Promise<boolean> {
324
+ const blacklisted = await this.blacklistPubSub.has(txOrigin.toLowerCase());
325
+
326
+ return blacklisted;
327
+
328
+ /*
329
+ rate-limit check was only if blacklist data set was not available,
330
+ in the current implementation it should not be the case,
331
+ so skip next check
332
+ */
333
+ // To not show pricing for rate limited users
334
+ if (await this.isRateLimited(txOrigin)) {
335
+ return true;
336
+ }
337
+
338
+ return false;
339
+ }
340
+
341
+ async setRateLimited(txOrigin: Address, ttl = DEXALOT_RATE_LIMITED_TTL_S) {
342
+ await this.dexHelper.cache.setex(
343
+ this.dexKey,
344
+ this.network,
345
+ this.getRateLimitedKey(txOrigin),
346
+ ttl,
347
+ DEXALOT_RATELIMIT_CACHE_VALUE,
348
+ );
349
+ return true;
350
+ }
351
+
352
+ async isRateLimited(txOrigin: Address): Promise<boolean> {
353
+ const result = await this.dexHelper.cache.get(
354
+ this.dexKey,
355
+ this.network,
356
+ this.getRateLimitedKey(txOrigin),
357
+ );
358
+ return result === DEXALOT_RATELIMIT_CACHE_VALUE;
359
+ }
360
+
361
+ getRateLimitedKey(address: Address) {
362
+ return `rate_limited_${address}`.toLowerCase();
363
+ }
364
+
365
+ async getCachedPrices(): Promise<PriceDataMap | null> {
366
+ const cachedPrices = await this.rateTokensPubSub.getAndCache(
367
+ this.pricesCacheKey,
368
+ );
369
+
370
+ if (cachedPrices) {
371
+ return cachedPrices as PriceDataMap;
372
+ }
373
+
374
+ return null;
375
+ }
376
+
377
+ async restrictPool(
378
+ poolIdentifier: string,
379
+ ttl: number = DEXALOT_RESTRICT_TTL_S,
380
+ ): Promise<boolean> {
381
+ await this.dexHelper.cache.setex(
382
+ this.dexKey,
383
+ this.network,
384
+ this.getRestrictedPoolKey(poolIdentifier),
385
+ ttl,
386
+ 'true',
387
+ );
388
+
389
+ await this.restrictedPoolPubSub.publish(
390
+ { [this.getRestrictedPoolKey(poolIdentifier)]: 'true' },
391
+ ttl,
392
+ );
393
+ return true;
394
+ }
395
+
396
+ async isRestrictedPool(poolIdentifier: string): Promise<boolean> {
397
+ const result = await this.restrictedPoolPubSub.getAndCache(
398
+ this.getRestrictedPoolKey(poolIdentifier),
399
+ );
400
+
401
+ return result === 'true';
402
+ }
403
+
404
+ getRestrictedPoolKey(poolIdentifier: string): string {
405
+ return `${DEXALOT_RESTRICTED_CACHE_KEY}-${poolIdentifier}`;
196
406
  }
197
407
  }
@@ -117,7 +117,6 @@ export type DexalotRateFetcherConfig = {
117
117
  tokensCacheKey: string;
118
118
  blacklistCacheKey: string;
119
119
  blacklistCacheTTLSecs: number;
120
- pairsCacheTTLSecs: number;
121
120
  pricesCacheTTLSecs: number;
122
121
  tokensCacheTTLSecs: number;
123
122
  };
@@ -46,7 +46,6 @@ export const reversePrice = (price: PriceAndAmountBigNumber) =>
46
46
  price[1].times(price[0]),
47
47
  ] as PriceAndAmountBigNumber;
48
48
 
49
- const logPrefix = 'RateFetched[pub_sub]';
50
49
  export class RateFetcher {
51
50
  private tokensFetcher: Fetcher<TokensResponse>;
52
51
  private pairsFetcher: Fetcher<PairsResponse>;
@@ -168,7 +167,6 @@ export class RateFetcher {
168
167
  }
169
168
 
170
169
  async initialize() {
171
- this.logger.info(`${logPrefix} Initializing rate fetcher`);
172
170
  const isContract = await isContractAddress(
173
171
  this.dexHelper.web3Provider,
174
172
  this.config.maker,
@@ -181,10 +179,8 @@ export class RateFetcher {
181
179
  }
182
180
 
183
181
  if (this.dexHelper.config.isSlave) {
184
- this.logger.info(`${logPrefix} Subscribing to prices pubsub`);
185
182
  this.pricesPubSub.subscribe();
186
183
  if (this.blacklistPubSub) {
187
- this.logger.info(`${logPrefix} Subscribing to blacklist pubsub`);
188
184
  const initSet = await this.dexHelper.cache.smembers(
189
185
  this.blackListCacheKey,
190
186
  );
@@ -194,7 +190,6 @@ export class RateFetcher {
194
190
  }
195
191
 
196
192
  start() {
197
- this.logger.info(`${logPrefix} Starting rate fetcher`);
198
193
  this.tokensFetcher.startPolling();
199
194
  this.rateFetcher.startPolling();
200
195
  this.pairsFetcher.startPolling();
@@ -204,7 +199,6 @@ export class RateFetcher {
204
199
  }
205
200
 
206
201
  stop() {
207
- this.logger.info(`${logPrefix} Stopping rate fetcher`);
208
202
  this.tokensFetcher.stopPolling();
209
203
  this.pairsFetcher.stopPolling();
210
204
  this.rateFetcher.stopPolling();
@@ -215,10 +209,6 @@ export class RateFetcher {
215
209
  }
216
210
 
217
211
  private handleTokensResponse(data: TokensResponse) {
218
- this.logger.info(
219
- `${logPrefix} Handling tokens response, tokens: `,
220
- Object.keys(data.tokens).length,
221
- );
222
212
  for (const tokenName of Object.keys(data.tokens)) {
223
213
  const token = data.tokens[tokenName];
224
214
  token.address = token.address.toLowerCase();
@@ -236,10 +226,6 @@ export class RateFetcher {
236
226
  }
237
227
 
238
228
  private handlePairsResponse(resp: PairsResponse) {
239
- this.logger.info(
240
- `${logPrefix} Handling pairs response, pairs: `,
241
- Object.keys(resp.pairs).length,
242
- );
243
229
  this.pairs = {};
244
230
 
245
231
  const pairs: PairMap = {};
@@ -251,19 +237,11 @@ export class RateFetcher {
251
237
  }
252
238
 
253
239
  private handleBlackListResponse(resp: BlackListResponse) {
254
- this.logger.info(
255
- `${logPrefix} Handling blacklist response, blacklist length: `,
256
- resp.blacklist.length,
257
- );
258
240
  for (const address of resp.blacklist) {
259
241
  this.dexHelper.cache.sadd(this.blackListCacheKey, address.toLowerCase());
260
242
  }
261
243
 
262
244
  if (this.blacklistPubSub) {
263
- this.logger.info(
264
- `${logPrefix} Publishing blacklist to pubsub, blacklist length: `,
265
- resp.blacklist.length,
266
- );
267
245
  this.blacklistPubSub.publish(resp.blacklist);
268
246
  }
269
247
  }
@@ -276,10 +254,6 @@ export class RateFetcher {
276
254
  }
277
255
 
278
256
  private handleRatesResponse(resp: RatesResponse) {
279
- this.logger.info(
280
- `${logPrefix} Handling rates response, prices length: `,
281
- Object.keys(resp.prices).length,
282
- );
283
257
  const pubSubData: Record<string, unknown> = {};
284
258
  const ttl = this.config.rateConfig.dataTTLS;
285
259
  const pairs = this.pairs;
@@ -395,10 +369,6 @@ export class RateFetcher {
395
369
 
396
370
  public async getAvailablePairs(): Promise<string[]> {
397
371
  const pairs = await this.pricesPubSub.getAndCache<string[]>(`pairs`);
398
- this.logger.info(
399
- `${logPrefix} Getting available pairs, pairs: `,
400
- pairs?.length,
401
- );
402
372
  if (!pairs) {
403
373
  return [];
404
374
  }
@@ -4,11 +4,11 @@ export const HASHFLOW_BLACKLIST_TTL_S = 60 * 60 * 24 * 7; // 7 days
4
4
 
5
5
  export const HASHFLOW_MM_RESTRICT_TTL_S = 60 * 60;
6
6
 
7
- export const HASHFLOW_PRICES_CACHES_TTL_S = 3;
7
+ export const HASHFLOW_PRICES_CACHES_TTL_S = 5;
8
8
 
9
9
  export const HASHFLOW_MARKET_MAKERS_CACHES_TTL_S = 30;
10
10
 
11
- export const HASHFLOW_API_PRICES_POLLING_INTERVAL_MS = 1000;
11
+ export const HASHFLOW_API_PRICES_POLLING_INTERVAL_MS = 2000;
12
12
 
13
13
  export const HASHFLOW_API_MARKET_MAKERS_POLLING_INTERVAL_MS = 28 * 1000; // 28 secs
14
14
 
@@ -1,10 +1,6 @@
1
1
  import { ChainId } from '@hashflow/sdk';
2
2
  import { Chain, ChainType, HashflowApi } from '@hashflow/taker-js';
3
- import {
4
- MarketMakersResponse,
5
- PriceLevelsResponse,
6
- RfqResponse,
7
- } from '@hashflow/taker-js/dist/types/rest';
3
+ import { RfqResponse } from '@hashflow/taker-js/dist/types/rest';
8
4
  import BigNumber from 'bignumber.js';
9
5
  import { Interface } from 'ethers/lib/utils';
10
6
  import { assert } from 'ts-essentials';
@@ -145,7 +141,6 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
145
141
  },
146
142
  headers: { Authorization: this.hashFlowAuthToken },
147
143
  },
148
- getCachedMarketMakers: this.getCachedMarketMakers.bind(this),
149
144
  filterMarketMakers: this.getFilteredMarketMakers.bind(this),
150
145
  pricesCacheKey: this.pricesCacheKey,
151
146
  pricesCacheTTLSecs: HASHFLOW_PRICES_CACHES_TTL_S,
@@ -157,9 +152,7 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
157
152
  }
158
153
 
159
154
  async initializePricing(blockNumber: number): Promise<void> {
160
- if (!this.dexHelper.config.isSlave) {
161
- this.rateFetcher.start();
162
- }
155
+ this.rateFetcher.start();
163
156
 
164
157
  return;
165
158
  }
@@ -198,7 +191,7 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
198
191
  return [];
199
192
  }
200
193
 
201
- const levels = (await this.getCachedLevels()) || {};
194
+ const levels = (await this.rateFetcher.getCachedLevels()) || {};
202
195
  const makers = Object.keys(levels);
203
196
 
204
197
  return makers
@@ -381,32 +374,6 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
381
374
  return undefined;
382
375
  }
383
376
 
384
- async getCachedMarketMakers(): Promise<
385
- MarketMakersResponse['marketMakers'] | null
386
- > {
387
- const cachedMarketMakers = await this.dexHelper.cache.rawget(
388
- this.marketMakersCacheKey,
389
- );
390
-
391
- if (cachedMarketMakers) {
392
- return JSON.parse(
393
- cachedMarketMakers,
394
- ) as MarketMakersResponse['marketMakers'];
395
- }
396
-
397
- return null;
398
- }
399
-
400
- async getCachedLevels(): Promise<PriceLevelsResponse['levels'] | null> {
401
- const cachedLevels = await this.dexHelper.cache.rawget(this.pricesCacheKey);
402
-
403
- if (cachedLevels) {
404
- return JSON.parse(cachedLevels) as PriceLevelsResponse['levels'];
405
- }
406
-
407
- return null;
408
- }
409
-
410
377
  async getPricesVolume(
411
378
  srcToken: Token,
412
379
  destToken: Token,
@@ -434,7 +401,7 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
434
401
 
435
402
  const marketMakersToUse = pools.map(p => p.split(`${prefix}_`).pop());
436
403
 
437
- const levelsMap = (await this.getCachedLevels()) || {};
404
+ const levelsMap = (await this.rateFetcher.getCachedLevels()) || {};
438
405
 
439
406
  Object.keys(levelsMap).forEach(mmKey => {
440
407
  if (!marketMakersToUse.includes(mmKey)) {
@@ -715,7 +682,7 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
715
682
  this.logger.warn(
716
683
  `${this.dexKey}-${this.network}: Encountered restricted user=${options.userAddress}. Adding to local blacklist cache`,
717
684
  );
718
- await this.setBlacklist(options.userAddress);
685
+ await this.rateFetcher.setBlacklist(options.userAddress);
719
686
  } else {
720
687
  if (e instanceof TooStrictSlippageCheckError) {
721
688
  this.logger.warn(
@@ -911,33 +878,6 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
911
878
  };
912
879
  }
913
880
 
914
- getBlackListKey(address: Address) {
915
- return `blacklist_${address}`.toLowerCase();
916
- }
917
-
918
- async isBlacklisted(txOrigin: Address): Promise<boolean> {
919
- const result = await this.dexHelper.cache.get(
920
- this.dexKey,
921
- this.network,
922
- this.getBlackListKey(txOrigin),
923
- );
924
- return result === 'blacklisted';
925
- }
926
-
927
- async setBlacklist(
928
- txOrigin: Address,
929
- ttl: number = HASHFLOW_BLACKLIST_TTL_S,
930
- ) {
931
- await this.dexHelper.cache.setex(
932
- this.dexKey,
933
- this.network,
934
- this.getBlackListKey(txOrigin),
935
- ttl,
936
- 'blacklisted',
937
- );
938
- return true;
939
- }
940
-
941
881
  async getSimpleParam(
942
882
  srcToken: string,
943
883
  destToken: string,
@@ -1058,9 +998,9 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
1058
998
  .wrapETH(tokenAddress)
1059
999
  .toLowerCase();
1060
1000
 
1061
- const makers = (await this.getCachedMarketMakers()) || [];
1001
+ const makers = (await this.rateFetcher.getCachedMarketMakers()) || [];
1062
1002
  const filteredMakers = await this.getFilteredMarketMakers(makers);
1063
- const pLevels = (await this.getCachedLevels()) || {};
1003
+ const pLevels = (await this.rateFetcher.getCachedLevels()) || {};
1064
1004
 
1065
1005
  let baseToken: Token | undefined = undefined;
1066
1006
  // TODO: Improve efficiency of this part. Quite inefficient way to determine
@@ -1120,4 +1060,8 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
1120
1060
  this.rateFetcher.stop();
1121
1061
  }
1122
1062
  }
1063
+
1064
+ async isBlacklisted(txOrigin: Address): Promise<boolean> {
1065
+ return this.rateFetcher.isBlacklisted(txOrigin);
1066
+ }
1123
1067
  }