Skip to content

Commit

Permalink
Merge pull request #93 from atomex-protocol/feat/atm-371-improve-atom…
Browse files Browse the repository at this point in the history
…ex-price-provider-common-top-of-book-cache

Improve atomex price provider common top of book cache
  • Loading branch information
skubarenko committed Sep 2, 2022
2 parents c165a4b + 91b608f commit 06871d3
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/atomexBuilder/atomexBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export class AtomexBuilder {
new Map<string, PriceProvider>([
['binance', new BinancePriceProvider()],
['kraken', new KrakenPriceProvider()],
['atomex', new AtomexPriceProvider(this.atomexContext.services.exchangeService)]
['atomex', new AtomexPriceProvider(this.atomexContext.managers.exchangeManager)]
]));
}
}
55 changes: 50 additions & 5 deletions src/exchange/exchangeManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { nanoid } from 'nanoid';

import type { AuthorizationManager } from '../authorization';
import { AtomexService, Currency, DataSource, ImportantDataReceivingMode, Side } from '../common/index';
import { EventEmitter, type ToEventEmitter } from '../core/index';
import { EventEmitter, Cache, InMemoryCache, type ToEventEmitter } from '../core/index';
import { toFixedBigNumber } from '../utils/converters';
import type { ExchangeService, ExchangeServiceEvents } from './exchangeService';
import type { ManagedExchangeSymbolsProvider } from './exchangeSymbolsProvider/index';
Expand Down Expand Up @@ -37,6 +37,7 @@ export class ExchangeManager implements AtomexService {
protected readonly orderBookProvider: ManagedOrderBookProvider;

private _isStarted = false;
private topOfBookCache: Cache = new InMemoryCache({ absoluteExpirationMs: 1000 * 60 });

constructor(options: ExchangeManagerOptions) {
this.authorizationManager = options.authorizationManager;
Expand Down Expand Up @@ -112,10 +113,26 @@ export class ExchangeManager implements AtomexService {
return [];
}

getTopOfBook(symbols?: string[]): Promise<Quote[]>;
getTopOfBook(directions?: CurrencyDirection[]): Promise<Quote[]>;
getTopOfBook(symbolsOrDirections?: string[] | CurrencyDirection[]): Promise<Quote[]> {
return (this.exchangeService.getTopOfBook as (symbolsOrDirections?: string[] | CurrencyDirection[]) => Promise<Quote[]>)(symbolsOrDirections);
getTopOfBook(symbols?: string[], dataSource?: DataSource): Promise<Quote[] | undefined>;
getTopOfBook(directions?: CurrencyDirection[], dataSource?: DataSource): Promise<Quote[] | undefined>;
async getTopOfBook(symbolsOrDirections?: string[] | CurrencyDirection[], dataSource = DataSource.All): Promise<Quote[] | undefined> {
const symbols = this.convertToSymbolsArray(symbolsOrDirections);
const key = this.getTopOfBookCacheKey(symbols);

if ((dataSource & DataSource.Local) === DataSource.Local) {
const cachedQuotes = this.topOfBookCache.get<Quote[]>(key);
if (cachedQuotes)
return cachedQuotes;
}

if ((dataSource & DataSource.Remote) === DataSource.Remote) {
const quotes = await (this.exchangeService.getTopOfBook as (symbolsOrDirections?: string[] | CurrencyDirection[]) => Promise<Quote[]>)(symbolsOrDirections);
this.topOfBookCache.set(key, quotes);

return quotes;
}

return undefined;
}

getOrderBook(symbol: string): Promise<OrderBook | undefined>;
Expand Down Expand Up @@ -335,4 +352,32 @@ export class ExchangeManager implements AtomexService {

return cachedOrderBook ? Promise.resolve(cachedOrderBook) : this.getOrderBook(symbol);
}

private getTopOfBookCacheKey(symbols: string[] | undefined) {
let postfix;

if (symbols && symbols.length) {
symbols.sort();
postfix = symbols.join(',');
} else
postfix = 'all';

return `top-of-book_${postfix}`;
}

private convertToSymbolsArray(symbolsOrDirections?: string[] | CurrencyDirection[]) {
let symbols: string[] | undefined = undefined;

if (symbolsOrDirections?.length) {
if (typeof symbolsOrDirections[0] === 'string')
symbols = [...symbolsOrDirections] as string[];
else {
const exchangeSymbols = this.symbolsProvider.getSymbolsMap();
symbols = (symbolsOrDirections as CurrencyDirection[])
.map(d => symbolsHelper.convertFromAndToCurrenciesToSymbolAndSide(exchangeSymbols, d.from, d.to)[0].name);
}
}

return symbols;
}
}
8 changes: 4 additions & 4 deletions src/exchange/priceProvider/atomex/atomexPriceProvider.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import type BigNumber from 'bignumber.js';

import type { Currency } from '../../../common/index';
import type { ExchangeService } from '../../exchangeService';
import { Currency, DataSource } from '../../../common/index';
import type { ExchangeManager } from '../../exchangeManager';
import type { Quote } from '../../models/index';
import type { PriceProvider } from '../priceProvider';

export class AtomexPriceProvider implements PriceProvider {
constructor(
private readonly exchangeService: ExchangeService
private readonly exchangeManager: ExchangeManager
) { }

async getPrice(baseCurrencyOrSymbol: Currency | string, quoteCurrencyOrSymbol: Currency | string): Promise<BigNumber | undefined> {
const baseCurrency = this.getSymbol(baseCurrencyOrSymbol);
const quoteCurrency = this.getSymbol(quoteCurrencyOrSymbol);
const pairSymbol = `${baseCurrency}/${quoteCurrency}`;

const quote = (await this.exchangeService.getTopOfBook([{ from: baseCurrency, to: quoteCurrency }]))?.[0];
const quote = (await this.exchangeManager.getTopOfBook([{ from: baseCurrency, to: quoteCurrency }], DataSource.Remote))?.[0];

return quote && quote.symbol === pairSymbol ? this.getMiddlePrice(quote) : undefined;
}
Expand Down

0 comments on commit 06871d3

Please sign in to comment.