From d9bd07c397d814c510be6374e98e03ab1fe8e968 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 15:58:52 +0300 Subject: [PATCH 01/19] Implement Kraken rates provider --- src/exchange/ratesProvider/index.ts | 3 ++ src/exchange/ratesProvider/kraken/dtos.ts | 51 +++++++++++++++++++ src/exchange/ratesProvider/kraken/index.ts | 1 + .../kraken/krakenRatesProvider.ts | 34 +++++++++++++ src/exchange/ratesProvider/ratesProvider.ts | 7 +++ 5 files changed, 96 insertions(+) create mode 100644 src/exchange/ratesProvider/index.ts create mode 100644 src/exchange/ratesProvider/kraken/dtos.ts create mode 100644 src/exchange/ratesProvider/kraken/index.ts create mode 100644 src/exchange/ratesProvider/kraken/krakenRatesProvider.ts create mode 100644 src/exchange/ratesProvider/ratesProvider.ts diff --git a/src/exchange/ratesProvider/index.ts b/src/exchange/ratesProvider/index.ts new file mode 100644 index 00000000..3e4f0e45 --- /dev/null +++ b/src/exchange/ratesProvider/index.ts @@ -0,0 +1,3 @@ +export type { RatesProvider } from './ratesProvider'; +export { BinanceRatesProvider } from './binance/index'; +export { KrakenRatesProvider } from './kraken/index'; diff --git a/src/exchange/ratesProvider/kraken/dtos.ts b/src/exchange/ratesProvider/kraken/dtos.ts new file mode 100644 index 00000000..1a65a792 --- /dev/null +++ b/src/exchange/ratesProvider/kraken/dtos.ts @@ -0,0 +1,51 @@ +export interface KrakenRatesDto { + error: string[]; + result: Record; +} + +export interface KrakenTickerInfo { + /** + * Ask + */ + a: [price: string, wholeLotVolume: string, lotVolume: string]; + + /** + * Bid + */ + b: [price: string, wholeLotVolume: string, lotVolume: string]; + + /** + * Last trade closed + */ + c: [price: string, lotVolume: string]; + + /** + * Volume + */ + v: [today: string, last24Hours: string]; + + /** + * Volume weighted average price + */ + p: [today: string, last24Hours: string]; + + /** + * Number of trades + */ + t: [today: number, last24Hours: number]; + + /** + * Low + */ + l: [today: string, last24Hours: string]; + + /** + * High + */ + h: [today: string, last24Hours: string]; + + /** + * Today's opening price + */ + o: string; +} diff --git a/src/exchange/ratesProvider/kraken/index.ts b/src/exchange/ratesProvider/kraken/index.ts new file mode 100644 index 00000000..882bb11d --- /dev/null +++ b/src/exchange/ratesProvider/kraken/index.ts @@ -0,0 +1 @@ +export { KrakenRatesProvider } from './krakenRatesProvider'; diff --git a/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts b/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts new file mode 100644 index 00000000..b43d0d17 --- /dev/null +++ b/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts @@ -0,0 +1,34 @@ +import BigNumber from 'bignumber.js'; + +import { HttpClient } from '../../../core'; +import type { RatesProvider } from '../ratesProvider'; +import type { KrakenRatesDto } from './dtos'; + +export class KrakenRatesProvider implements RatesProvider { + private static readonly baseUrl = 'https://api.kraken.com'; + + private readonly httpClient: HttpClient; + + constructor() { + this.httpClient = new HttpClient(KrakenRatesProvider.baseUrl); + } + + async getPrice(quoteCurrency: string, baseCurrency: string): Promise { + const symbol = `${quoteCurrency}${baseCurrency}`; + const urlPath = `/0/public/Ticker?pair=${symbol}`; + const responseDto = await this.httpClient.request({ urlPath }, false); + + return this.mapRatesDtoToPrice(responseDto, symbol); + } + + private mapRatesDtoToPrice(dto: KrakenRatesDto, symbol: string): BigNumber | undefined { + if (dto.error) + return undefined; + + const tickerInfo = dto.result[symbol]; + if (!tickerInfo) + return undefined; + + return new BigNumber(tickerInfo.c[0]); + } +} diff --git a/src/exchange/ratesProvider/ratesProvider.ts b/src/exchange/ratesProvider/ratesProvider.ts new file mode 100644 index 00000000..169c2862 --- /dev/null +++ b/src/exchange/ratesProvider/ratesProvider.ts @@ -0,0 +1,7 @@ +import type BigNumber from 'bignumber.js'; + +import type { Currency } from '../../common'; + +export interface RatesProvider { + getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id']): Promise; +} From cd915de4a4baff3165ba55add649168f06654de0 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 15:59:04 +0300 Subject: [PATCH 02/19] Implement Binance rates provider --- .../binance/binanceRatesProvider.ts | 30 +++++++++++++++++++ src/exchange/ratesProvider/binance/dtos.ts | 9 ++++++ src/exchange/ratesProvider/binance/index.ts | 1 + src/exchange/ratesProvider/binance/utils.ts | 6 ++++ 4 files changed, 46 insertions(+) create mode 100644 src/exchange/ratesProvider/binance/binanceRatesProvider.ts create mode 100644 src/exchange/ratesProvider/binance/dtos.ts create mode 100644 src/exchange/ratesProvider/binance/index.ts create mode 100644 src/exchange/ratesProvider/binance/utils.ts diff --git a/src/exchange/ratesProvider/binance/binanceRatesProvider.ts b/src/exchange/ratesProvider/binance/binanceRatesProvider.ts new file mode 100644 index 00000000..1f52a375 --- /dev/null +++ b/src/exchange/ratesProvider/binance/binanceRatesProvider.ts @@ -0,0 +1,30 @@ +import BigNumber from 'bignumber.js'; + +import { HttpClient } from '../../../core'; +import type { RatesProvider } from '../ratesProvider'; +import type { BinanceErrorDto, BinanceRatesDto } from './dtos'; +import { isErrorDto } from './utils'; + +export class BinanceRatesProvider implements RatesProvider { + private static readonly baseUrl = 'https://www.binance.com/api'; + + private readonly httpClient: HttpClient; + + constructor() { + this.httpClient = new HttpClient(BinanceRatesProvider.baseUrl); + } + + async getPrice(quoteCurrency: string, baseCurrency: string): Promise { + const urlPath = `/v3/ticker/price?symbol=${quoteCurrency}${baseCurrency}`; + const responseDto = await this.httpClient.request({ urlPath }, false); + + return this.mapRatesDtoToPrice(responseDto); + } + + private mapRatesDtoToPrice(dto: BinanceRatesDto | BinanceErrorDto): BigNumber | undefined { + if (isErrorDto(dto)) + return undefined; + + return new BigNumber(dto.price); + } +} diff --git a/src/exchange/ratesProvider/binance/dtos.ts b/src/exchange/ratesProvider/binance/dtos.ts new file mode 100644 index 00000000..1e308a92 --- /dev/null +++ b/src/exchange/ratesProvider/binance/dtos.ts @@ -0,0 +1,9 @@ +export interface BinanceRatesDto { + symbol: string; + price: string; +} + +export interface BinanceErrorDto { + code: number; + msg: string; +} diff --git a/src/exchange/ratesProvider/binance/index.ts b/src/exchange/ratesProvider/binance/index.ts new file mode 100644 index 00000000..e915cbb9 --- /dev/null +++ b/src/exchange/ratesProvider/binance/index.ts @@ -0,0 +1 @@ +export { BinanceRatesProvider } from './binanceRatesProvider'; diff --git a/src/exchange/ratesProvider/binance/utils.ts b/src/exchange/ratesProvider/binance/utils.ts new file mode 100644 index 00000000..f7b8f602 --- /dev/null +++ b/src/exchange/ratesProvider/binance/utils.ts @@ -0,0 +1,6 @@ +import type { BinanceErrorDto } from './dtos'; + +export const isErrorDto = (dto: unknown): dto is BinanceErrorDto => { + const errorDto = dto as BinanceErrorDto; + return typeof errorDto.code === 'number' && typeof errorDto.msg === 'string'; +}; From ce2c372d062d3ee02dbb73defed4d0ac4c25e187 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 16:08:33 +0300 Subject: [PATCH 03/19] Refactor --- src/exchange/ratesProvider/binance/binanceRatesProvider.ts | 3 ++- src/exchange/ratesProvider/kraken/krakenRatesProvider.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/exchange/ratesProvider/binance/binanceRatesProvider.ts b/src/exchange/ratesProvider/binance/binanceRatesProvider.ts index 1f52a375..1415c156 100644 --- a/src/exchange/ratesProvider/binance/binanceRatesProvider.ts +++ b/src/exchange/ratesProvider/binance/binanceRatesProvider.ts @@ -1,5 +1,6 @@ import BigNumber from 'bignumber.js'; +import type { Currency } from '../../../common'; import { HttpClient } from '../../../core'; import type { RatesProvider } from '../ratesProvider'; import type { BinanceErrorDto, BinanceRatesDto } from './dtos'; @@ -14,7 +15,7 @@ export class BinanceRatesProvider implements RatesProvider { this.httpClient = new HttpClient(BinanceRatesProvider.baseUrl); } - async getPrice(quoteCurrency: string, baseCurrency: string): Promise { + async getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id']): Promise { const urlPath = `/v3/ticker/price?symbol=${quoteCurrency}${baseCurrency}`; const responseDto = await this.httpClient.request({ urlPath }, false); diff --git a/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts b/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts index b43d0d17..547d0e4d 100644 --- a/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts +++ b/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts @@ -1,5 +1,6 @@ import BigNumber from 'bignumber.js'; +import type { Currency } from '../../../common'; import { HttpClient } from '../../../core'; import type { RatesProvider } from '../ratesProvider'; import type { KrakenRatesDto } from './dtos'; @@ -13,7 +14,7 @@ export class KrakenRatesProvider implements RatesProvider { this.httpClient = new HttpClient(KrakenRatesProvider.baseUrl); } - async getPrice(quoteCurrency: string, baseCurrency: string): Promise { + async getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id']): Promise { const symbol = `${quoteCurrency}${baseCurrency}`; const urlPath = `/0/public/Ticker?pair=${symbol}`; const responseDto = await this.httpClient.request({ urlPath }, false); From d27b24552007255e9830509fef9cce6b9b94a690 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 16:20:10 +0300 Subject: [PATCH 04/19] Implement MixedRatesProvider --- .../ratesProvider/aggregatedRatesProvider.ts | 7 ++++ src/exchange/ratesProvider/index.ts | 2 ++ .../ratesProvider/mixedRatesProvider/index.ts | 1 + .../mixedRatesProvider/mixedRatesProvider.ts | 34 +++++++++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 src/exchange/ratesProvider/aggregatedRatesProvider.ts create mode 100644 src/exchange/ratesProvider/mixedRatesProvider/index.ts create mode 100644 src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts diff --git a/src/exchange/ratesProvider/aggregatedRatesProvider.ts b/src/exchange/ratesProvider/aggregatedRatesProvider.ts new file mode 100644 index 00000000..be3ffa27 --- /dev/null +++ b/src/exchange/ratesProvider/aggregatedRatesProvider.ts @@ -0,0 +1,7 @@ +import type BigNumber from 'bignumber.js'; + +import type { Currency } from '../../common'; + +export interface AggregatedRatesProvider { + getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id'], provider?: string): Promise; +} diff --git a/src/exchange/ratesProvider/index.ts b/src/exchange/ratesProvider/index.ts index 3e4f0e45..6741a071 100644 --- a/src/exchange/ratesProvider/index.ts +++ b/src/exchange/ratesProvider/index.ts @@ -1,3 +1,5 @@ export type { RatesProvider } from './ratesProvider'; +export type { AggregatedRatesProvider } from './aggregatedRatesProvider'; export { BinanceRatesProvider } from './binance/index'; export { KrakenRatesProvider } from './kraken/index'; +export { MixedRatesProvider } from './mixedRatesProvider/index'; diff --git a/src/exchange/ratesProvider/mixedRatesProvider/index.ts b/src/exchange/ratesProvider/mixedRatesProvider/index.ts new file mode 100644 index 00000000..4085da3f --- /dev/null +++ b/src/exchange/ratesProvider/mixedRatesProvider/index.ts @@ -0,0 +1 @@ +export { MixedRatesProvider } from './mixedRatesProvider'; diff --git a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts new file mode 100644 index 00000000..e7695d15 --- /dev/null +++ b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts @@ -0,0 +1,34 @@ +import type BigNumber from 'bignumber.js'; + +import type { Currency } from '../../../common'; +import type { AggregatedRatesProvider } from '../aggregatedRatesProvider'; +import type { RatesProvider } from '../ratesProvider'; + +export class MixedRatesProvider implements AggregatedRatesProvider { + constructor( + private readonly providersMap: Map + ) { } + + async getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id'], provider?: string): Promise { + const providers = this.getAvailableProviders(provider); + const pricePromises = providers.map(p => p.getPrice(quoteCurrency, baseCurrency)); + const pricePromiseResults = await Promise.allSettled(pricePromises); + + for (const result of pricePromiseResults) + if (result.status === 'fulfilled' && result.value !== undefined) + return result.value; + + return undefined; + } + + private getAvailableProviders(provider?: string): RatesProvider[] { + if (!provider) + return [...this.providersMap.values()]; + + const selectedProvider = this.providersMap.get(provider); + if (!selectedProvider) + throw new Error(`Provider not found for key: ${provider}`); + + return [selectedProvider]; + } +} From 25e42820dbdd4c796ab75bf1f91d10011a7ff212 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 16:29:17 +0300 Subject: [PATCH 05/19] Refactor aggregated provider; Fix export --- src/exchange/index.ts | 5 +++++ src/exchange/ratesProvider/aggregatedRatesProvider.ts | 1 + .../mixedRatesProvider/mixedRatesProvider.ts | 8 ++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/exchange/index.ts b/src/exchange/index.ts index 8cbce218..5e220625 100644 --- a/src/exchange/index.ts +++ b/src/exchange/index.ts @@ -8,3 +8,8 @@ export { InMemoryOrderBookProvider } from './orderBookProvider/index'; export type { ExchangeSymbolsProvider, ManagedExchangeSymbolsProvider } from './exchangeSymbolsProvider/index'; export type { OrderBookProvider, ManagedOrderBookProvider } from './orderBookProvider/index'; export type { ExchangeService, ExchangeServiceEvents } from './exchangeService'; + +export { + type RatesProvider, type AggregatedRatesProvider, + BinanceRatesProvider, KrakenRatesProvider, MixedRatesProvider, +} from './ratesProvider/index'; diff --git a/src/exchange/ratesProvider/aggregatedRatesProvider.ts b/src/exchange/ratesProvider/aggregatedRatesProvider.ts index be3ffa27..70e65a67 100644 --- a/src/exchange/ratesProvider/aggregatedRatesProvider.ts +++ b/src/exchange/ratesProvider/aggregatedRatesProvider.ts @@ -4,4 +4,5 @@ import type { Currency } from '../../common'; export interface AggregatedRatesProvider { getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id'], provider?: string): Promise; + getAvailableProviders(): string[]; } diff --git a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts index e7695d15..2c75fc28 100644 --- a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts +++ b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts @@ -10,7 +10,7 @@ export class MixedRatesProvider implements AggregatedRatesProvider { ) { } async getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id'], provider?: string): Promise { - const providers = this.getAvailableProviders(provider); + const providers = this.getSelectedProviders(provider); const pricePromises = providers.map(p => p.getPrice(quoteCurrency, baseCurrency)); const pricePromiseResults = await Promise.allSettled(pricePromises); @@ -21,7 +21,11 @@ export class MixedRatesProvider implements AggregatedRatesProvider { return undefined; } - private getAvailableProviders(provider?: string): RatesProvider[] { + getAvailableProviders(): string[] { + return [...this.providersMap.keys()]; + } + + private getSelectedProviders(provider?: string): RatesProvider[] { if (!provider) return [...this.providersMap.values()]; From c4f09915d374e45da3dca3ee0bc32d72d6683f1a Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 16:34:20 +0300 Subject: [PATCH 06/19] Inject rates provider into atomex context --- src/atomex/atomexContext.ts | 14 +++++++++++++- src/atomexBuilder/atomexBuilder.ts | 13 ++++++++++++- src/atomexBuilder/controlledAtomexContext.ts | 5 ++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/atomex/atomexContext.ts b/src/atomex/atomexContext.ts index 53fd9c1b..a8a1876a 100644 --- a/src/atomex/atomexContext.ts +++ b/src/atomex/atomexContext.ts @@ -1,7 +1,7 @@ import type { AuthorizationManager } from '../authorization/index'; import type { WalletsManager, AtomexBlockchainProvider } from '../blockchain/index'; import type { AtomexNetwork, CurrenciesProvider } from '../common/index'; -import type { ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider } from '../exchange/index'; +import type { AggregatedRatesProvider, ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider } from '../exchange/index'; import type { SwapManager, SwapService } from '../swaps/index'; export class AtomexContext { @@ -111,6 +111,7 @@ class AtomexContextProvidersSection { private _currenciesProvider: CurrenciesProvider | undefined; private _exchangeSymbolsProvider: ManagedExchangeSymbolsProvider | undefined; private _orderBookProvider: ManagedOrderBookProvider | undefined; + private _ratesProvider: AggregatedRatesProvider | undefined; constructor(readonly context: AtomexContext) { } @@ -158,6 +159,17 @@ class AtomexContextProvidersSection { private set orderBookProvider(orderBookProvider: ManagedOrderBookProvider) { this._orderBookProvider = orderBookProvider; } + + get ratesProvider(): AggregatedRatesProvider { + if (!this._ratesProvider) + throw new AtomexComponentNotResolvedError('providers.ratesProvider'); + + return this._ratesProvider; + } + + private set ratesProvider(ratesProvider: AggregatedRatesProvider) { + this._ratesProvider = ratesProvider; + } } export class AtomexComponentNotResolvedError extends Error { diff --git a/src/atomexBuilder/atomexBuilder.ts b/src/atomexBuilder/atomexBuilder.ts index 9686fe2d..82031bc2 100644 --- a/src/atomexBuilder/atomexBuilder.ts +++ b/src/atomexBuilder/atomexBuilder.ts @@ -4,7 +4,10 @@ import type { AuthorizationManager } from '../authorization/index'; import { AtomexBlockchainProvider, WalletsManager } from '../blockchain/index'; import type { DeepReadonly } from '../core/index'; import { createDefaultEthereumBlockchainOptions } from '../ethereum/index'; -import { ExchangeManager, InMemoryExchangeSymbolsProvider, InMemoryOrderBookProvider } from '../exchange/index'; +import { + AggregatedRatesProvider, BinanceRatesProvider, ExchangeManager, InMemoryExchangeSymbolsProvider, + InMemoryOrderBookProvider, KrakenRatesProvider, MixedRatesProvider, RatesProvider +} from '../exchange/index'; import { SwapManager } from '../swaps/swapManager'; import { createDefaultTezosBlockchainOptions } from '../tezos/index'; import type { AtomexBuilderOptions } from './atomexBuilderOptions'; @@ -48,6 +51,7 @@ export class AtomexBuilder { const blockchainProvider = new AtomexBlockchainProvider(); this.controlledAtomexContext.providers.blockchainProvider = blockchainProvider; this.controlledAtomexContext.providers.currenciesProvider = blockchainProvider; + this.controlledAtomexContext.providers.ratesProvider = this.createRatesProvider(); this.controlledAtomexContext.providers.exchangeSymbolsProvider = this.createExchangeSymbolsProvider(); this.controlledAtomexContext.providers.orderBookProvider = this.createOrderBookProvider(); this.controlledAtomexContext.managers.walletsManager = this.createWalletsManager(); @@ -119,4 +123,11 @@ export class AtomexBuilder { ethereum: createDefaultEthereumBlockchainOptions(this.atomexContext) }; } + + protected createRatesProvider(): AggregatedRatesProvider { + return new MixedRatesProvider(new Map([ + ['binance', new BinanceRatesProvider()], + ['kraken', new KrakenRatesProvider()], + ])); + } } diff --git a/src/atomexBuilder/controlledAtomexContext.ts b/src/atomexBuilder/controlledAtomexContext.ts index d24af2fb..12c9b827 100644 --- a/src/atomexBuilder/controlledAtomexContext.ts +++ b/src/atomexBuilder/controlledAtomexContext.ts @@ -2,7 +2,7 @@ import type { AuthorizationManager } from '../authorization/index'; import type { AtomexBlockchainProvider } from '../blockchain/atomexBlockchainProvider'; import type { WalletsManager } from '../blockchain/index'; import type { AtomexNetwork, CurrenciesProvider } from '../common/index'; -import type { ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider } from '../exchange/index'; +import type { AggregatedRatesProvider, ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider } from '../exchange/index'; import type { SwapManager, SwapService } from '../swaps/index'; export interface ControlledAtomexContext { @@ -48,4 +48,7 @@ interface ControlledAtomexContextProvidersSection { get orderBookProvider(): ManagedOrderBookProvider; set orderBookProvider(value: ManagedOrderBookProvider); + + get ratesProvider(): AggregatedRatesProvider; + set ratesProvider(value: AggregatedRatesProvider); } From 416e53267b9ff464a11e438326519e872be69640 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 17:46:46 +0300 Subject: [PATCH 07/19] Implement AtomexRatesProvider --- src/atomexBuilder/atomexBuilder.ts | 5 +++-- src/exchange/index.ts | 2 +- .../atomex/atomexRatesProvider.ts | 22 +++++++++++++++++++ src/exchange/ratesProvider/atomex/index.ts | 1 + src/exchange/ratesProvider/index.ts | 1 + 5 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 src/exchange/ratesProvider/atomex/atomexRatesProvider.ts create mode 100644 src/exchange/ratesProvider/atomex/index.ts diff --git a/src/atomexBuilder/atomexBuilder.ts b/src/atomexBuilder/atomexBuilder.ts index 82031bc2..24d5cc39 100644 --- a/src/atomexBuilder/atomexBuilder.ts +++ b/src/atomexBuilder/atomexBuilder.ts @@ -5,7 +5,7 @@ import { AtomexBlockchainProvider, WalletsManager } from '../blockchain/index'; import type { DeepReadonly } from '../core/index'; import { createDefaultEthereumBlockchainOptions } from '../ethereum/index'; import { - AggregatedRatesProvider, BinanceRatesProvider, ExchangeManager, InMemoryExchangeSymbolsProvider, + AggregatedRatesProvider, AtomexRatesProvider, BinanceRatesProvider, ExchangeManager, InMemoryExchangeSymbolsProvider, InMemoryOrderBookProvider, KrakenRatesProvider, MixedRatesProvider, RatesProvider } from '../exchange/index'; import { SwapManager } from '../swaps/swapManager'; @@ -51,7 +51,6 @@ export class AtomexBuilder { const blockchainProvider = new AtomexBlockchainProvider(); this.controlledAtomexContext.providers.blockchainProvider = blockchainProvider; this.controlledAtomexContext.providers.currenciesProvider = blockchainProvider; - this.controlledAtomexContext.providers.ratesProvider = this.createRatesProvider(); this.controlledAtomexContext.providers.exchangeSymbolsProvider = this.createExchangeSymbolsProvider(); this.controlledAtomexContext.providers.orderBookProvider = this.createOrderBookProvider(); this.controlledAtomexContext.managers.walletsManager = this.createWalletsManager(); @@ -61,6 +60,7 @@ export class AtomexBuilder { this.controlledAtomexContext.services.swapService = atomexClient; this.controlledAtomexContext.managers.exchangeManager = this.createExchangeManager(); this.controlledAtomexContext.managers.swapManager = this.createSwapManager(); + this.controlledAtomexContext.providers.ratesProvider = this.createRatesProvider(); const blockchains = this.createDefaultBlockchainOptions(); return new Atomex({ @@ -128,6 +128,7 @@ export class AtomexBuilder { return new MixedRatesProvider(new Map([ ['binance', new BinanceRatesProvider()], ['kraken', new KrakenRatesProvider()], + ['atomex', new AtomexRatesProvider(this.atomexContext.services.exchangeService)] ])); } } diff --git a/src/exchange/index.ts b/src/exchange/index.ts index 5e220625..d1eb4615 100644 --- a/src/exchange/index.ts +++ b/src/exchange/index.ts @@ -11,5 +11,5 @@ export type { ExchangeService, ExchangeServiceEvents } from './exchangeService'; export { type RatesProvider, type AggregatedRatesProvider, - BinanceRatesProvider, KrakenRatesProvider, MixedRatesProvider, + BinanceRatesProvider, KrakenRatesProvider, MixedRatesProvider, AtomexRatesProvider } from './ratesProvider/index'; diff --git a/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts b/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts new file mode 100644 index 00000000..9781e166 --- /dev/null +++ b/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts @@ -0,0 +1,22 @@ +import type BigNumber from 'bignumber.js'; + +import type { Currency } from '../../../common/index'; +import type { ExchangeService } from '../../exchangeService'; +import type { Quote } from '../../models/index'; +import type { RatesProvider } from '../ratesProvider'; + +export class AtomexRatesProvider implements RatesProvider { + constructor( + private readonly exchangeService: ExchangeService + ) { } + + async getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id']): Promise { + const quote = (await this.exchangeService.getTopOfBook([{ from: quoteCurrency, to: baseCurrency }]))?.[0]; + + return quote ? this.getMiddlePrice(quote) : undefined; + } + + private getMiddlePrice(quote: Quote): BigNumber { + return quote.ask.plus(quote.bid).div(2); + } +} diff --git a/src/exchange/ratesProvider/atomex/index.ts b/src/exchange/ratesProvider/atomex/index.ts new file mode 100644 index 00000000..9a5b4b7b --- /dev/null +++ b/src/exchange/ratesProvider/atomex/index.ts @@ -0,0 +1 @@ +export { AtomexRatesProvider } from './atomexRatesProvider'; diff --git a/src/exchange/ratesProvider/index.ts b/src/exchange/ratesProvider/index.ts index 6741a071..b9e153e7 100644 --- a/src/exchange/ratesProvider/index.ts +++ b/src/exchange/ratesProvider/index.ts @@ -1,5 +1,6 @@ export type { RatesProvider } from './ratesProvider'; export type { AggregatedRatesProvider } from './aggregatedRatesProvider'; +export { AtomexRatesProvider } from './atomex/index'; export { BinanceRatesProvider } from './binance/index'; export { KrakenRatesProvider } from './kraken/index'; export { MixedRatesProvider } from './mixedRatesProvider/index'; From c63b71be0d8619fcfde6b778fcc27feb400c14e4 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 18:02:34 +0300 Subject: [PATCH 08/19] Rename parameters according to common agreement --- src/exchange/ratesProvider/aggregatedRatesProvider.ts | 2 +- src/exchange/ratesProvider/atomex/atomexRatesProvider.ts | 2 +- src/exchange/ratesProvider/binance/binanceRatesProvider.ts | 4 ++-- src/exchange/ratesProvider/kraken/krakenRatesProvider.ts | 4 ++-- .../ratesProvider/mixedRatesProvider/mixedRatesProvider.ts | 4 ++-- src/exchange/ratesProvider/ratesProvider.ts | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/exchange/ratesProvider/aggregatedRatesProvider.ts b/src/exchange/ratesProvider/aggregatedRatesProvider.ts index 70e65a67..7bdec52b 100644 --- a/src/exchange/ratesProvider/aggregatedRatesProvider.ts +++ b/src/exchange/ratesProvider/aggregatedRatesProvider.ts @@ -3,6 +3,6 @@ import type BigNumber from 'bignumber.js'; import type { Currency } from '../../common'; export interface AggregatedRatesProvider { - getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id'], provider?: string): Promise; + getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise; getAvailableProviders(): string[]; } diff --git a/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts b/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts index 9781e166..789f0fe9 100644 --- a/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts +++ b/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts @@ -10,7 +10,7 @@ export class AtomexRatesProvider implements RatesProvider { private readonly exchangeService: ExchangeService ) { } - async getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id']): Promise { + async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise { const quote = (await this.exchangeService.getTopOfBook([{ from: quoteCurrency, to: baseCurrency }]))?.[0]; return quote ? this.getMiddlePrice(quote) : undefined; diff --git a/src/exchange/ratesProvider/binance/binanceRatesProvider.ts b/src/exchange/ratesProvider/binance/binanceRatesProvider.ts index 1415c156..5338215f 100644 --- a/src/exchange/ratesProvider/binance/binanceRatesProvider.ts +++ b/src/exchange/ratesProvider/binance/binanceRatesProvider.ts @@ -15,8 +15,8 @@ export class BinanceRatesProvider implements RatesProvider { this.httpClient = new HttpClient(BinanceRatesProvider.baseUrl); } - async getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id']): Promise { - const urlPath = `/v3/ticker/price?symbol=${quoteCurrency}${baseCurrency}`; + async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise { + const urlPath = `/v3/ticker/price?symbol=${baseCurrency}${quoteCurrency}`; const responseDto = await this.httpClient.request({ urlPath }, false); return this.mapRatesDtoToPrice(responseDto); diff --git a/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts b/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts index 547d0e4d..77c324c6 100644 --- a/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts +++ b/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts @@ -14,8 +14,8 @@ export class KrakenRatesProvider implements RatesProvider { this.httpClient = new HttpClient(KrakenRatesProvider.baseUrl); } - async getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id']): Promise { - const symbol = `${quoteCurrency}${baseCurrency}`; + async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise { + const symbol = `${baseCurrency}${quoteCurrency}`; const urlPath = `/0/public/Ticker?pair=${symbol}`; const responseDto = await this.httpClient.request({ urlPath }, false); diff --git a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts index 2c75fc28..525fac05 100644 --- a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts +++ b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts @@ -9,9 +9,9 @@ export class MixedRatesProvider implements AggregatedRatesProvider { private readonly providersMap: Map ) { } - async getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id'], provider?: string): Promise { + async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise { const providers = this.getSelectedProviders(provider); - const pricePromises = providers.map(p => p.getPrice(quoteCurrency, baseCurrency)); + const pricePromises = providers.map(p => p.getPrice(baseCurrency, quoteCurrency)); const pricePromiseResults = await Promise.allSettled(pricePromises); for (const result of pricePromiseResults) diff --git a/src/exchange/ratesProvider/ratesProvider.ts b/src/exchange/ratesProvider/ratesProvider.ts index 169c2862..40afb082 100644 --- a/src/exchange/ratesProvider/ratesProvider.ts +++ b/src/exchange/ratesProvider/ratesProvider.ts @@ -3,5 +3,5 @@ import type BigNumber from 'bignumber.js'; import type { Currency } from '../../common'; export interface RatesProvider { - getPrice(quoteCurrency: Currency['id'], baseCurrency: Currency['id']): Promise; + getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise; } From 2a199ceae51c3af23236f9a06cf7e225e4b89a95 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 19:49:00 +0300 Subject: [PATCH 09/19] Fix binance url --- src/exchange/ratesProvider/binance/binanceRatesProvider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/exchange/ratesProvider/binance/binanceRatesProvider.ts b/src/exchange/ratesProvider/binance/binanceRatesProvider.ts index 5338215f..914f6518 100644 --- a/src/exchange/ratesProvider/binance/binanceRatesProvider.ts +++ b/src/exchange/ratesProvider/binance/binanceRatesProvider.ts @@ -7,7 +7,7 @@ import type { BinanceErrorDto, BinanceRatesDto } from './dtos'; import { isErrorDto } from './utils'; export class BinanceRatesProvider implements RatesProvider { - private static readonly baseUrl = 'https://www.binance.com/api'; + private static readonly baseUrl = 'https://www.binance.com'; private readonly httpClient: HttpClient; @@ -16,7 +16,7 @@ export class BinanceRatesProvider implements RatesProvider { } async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise { - const urlPath = `/v3/ticker/price?symbol=${baseCurrency}${quoteCurrency}`; + const urlPath = `/api/v3/ticker/price?symbol=${baseCurrency}${quoteCurrency}`; const responseDto = await this.httpClient.request({ urlPath }, false); return this.mapRatesDtoToPrice(responseDto); From 89f7116fce8fe08976f4c15552203758e3615b7c Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 20:19:21 +0300 Subject: [PATCH 10/19] Fix price calculation --- .../atomex/atomexRatesProvider.ts | 3 ++- .../kraken/krakenRatesProvider.ts | 2 +- .../mixedRatesProvider/mixedRatesProvider.ts | 19 +++++++++++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts b/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts index 789f0fe9..b0b2a092 100644 --- a/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts +++ b/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts @@ -11,7 +11,8 @@ export class AtomexRatesProvider implements RatesProvider { ) { } async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise { - const quote = (await this.exchangeService.getTopOfBook([{ from: quoteCurrency, to: baseCurrency }]))?.[0]; + const symbol = `${baseCurrency}/${quoteCurrency}`; + const quote = (await this.exchangeService.getTopOfBook([symbol]))?.[0]; return quote ? this.getMiddlePrice(quote) : undefined; } diff --git a/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts b/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts index 77c324c6..46b92589 100644 --- a/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts +++ b/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts @@ -23,7 +23,7 @@ export class KrakenRatesProvider implements RatesProvider { } private mapRatesDtoToPrice(dto: KrakenRatesDto, symbol: string): BigNumber | undefined { - if (dto.error) + if (dto.error.length) return undefined; const tickerInfo = dto.result[symbol]; diff --git a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts index 525fac05..286d591c 100644 --- a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts +++ b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts @@ -10,6 +10,21 @@ export class MixedRatesProvider implements AggregatedRatesProvider { ) { } async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise { + let price = await this.getPriceCore(baseCurrency, quoteCurrency, provider); + if (!price) { + const reversedPrice = await this.getPriceCore(quoteCurrency, baseCurrency, provider); + if (reversedPrice) + price = reversedPrice.pow(-1); + } + + return price; + } + + getAvailableProviders(): string[] { + return [...this.providersMap.keys()]; + } + + private async getPriceCore(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise { const providers = this.getSelectedProviders(provider); const pricePromises = providers.map(p => p.getPrice(baseCurrency, quoteCurrency)); const pricePromiseResults = await Promise.allSettled(pricePromises); @@ -21,10 +36,6 @@ export class MixedRatesProvider implements AggregatedRatesProvider { return undefined; } - getAvailableProviders(): string[] { - return [...this.providersMap.keys()]; - } - private getSelectedProviders(provider?: string): RatesProvider[] { if (!provider) return [...this.providersMap.values()]; From f6dbaa9cd0d437df40839e813c5f90bcc9f796e9 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 20:33:26 +0300 Subject: [PATCH 11/19] Fix kraken dto parsing --- src/exchange/ratesProvider/kraken/krakenRatesProvider.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts b/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts index 46b92589..c8411fe8 100644 --- a/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts +++ b/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts @@ -19,14 +19,15 @@ export class KrakenRatesProvider implements RatesProvider { const urlPath = `/0/public/Ticker?pair=${symbol}`; const responseDto = await this.httpClient.request({ urlPath }, false); - return this.mapRatesDtoToPrice(responseDto, symbol); + return this.mapRatesDtoToPrice(responseDto); } - private mapRatesDtoToPrice(dto: KrakenRatesDto, symbol: string): BigNumber | undefined { + private mapRatesDtoToPrice(dto: KrakenRatesDto): BigNumber | undefined { if (dto.error.length) return undefined; - const tickerInfo = dto.result[symbol]; + const symbol = Object.keys(dto.result)[0]; + const tickerInfo = symbol ? dto.result[symbol] : undefined; if (!tickerInfo) return undefined; From e0cdee9f1f81d33fd6fc992e9b77e3d3de7446d6 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 21:16:03 +0300 Subject: [PATCH 12/19] Reduce bad requests count --- .../atomex/atomexRatesProvider.ts | 4 ++-- .../binance/binanceRatesProvider.ts | 23 ++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts b/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts index b0b2a092..3e8bc7a1 100644 --- a/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts +++ b/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts @@ -12,9 +12,9 @@ export class AtomexRatesProvider implements RatesProvider { async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise { const symbol = `${baseCurrency}/${quoteCurrency}`; - const quote = (await this.exchangeService.getTopOfBook([symbol]))?.[0]; + const quote = (await this.exchangeService.getTopOfBook([{ from: baseCurrency, to: quoteCurrency }]))?.[0]; - return quote ? this.getMiddlePrice(quote) : undefined; + return quote && quote.symbol == symbol ? this.getMiddlePrice(quote) : undefined; } private getMiddlePrice(quote: Quote): BigNumber { diff --git a/src/exchange/ratesProvider/binance/binanceRatesProvider.ts b/src/exchange/ratesProvider/binance/binanceRatesProvider.ts index 914f6518..58ad1d46 100644 --- a/src/exchange/ratesProvider/binance/binanceRatesProvider.ts +++ b/src/exchange/ratesProvider/binance/binanceRatesProvider.ts @@ -8,15 +8,22 @@ import { isErrorDto } from './utils'; export class BinanceRatesProvider implements RatesProvider { private static readonly baseUrl = 'https://www.binance.com'; + private static readonly priceUrlPath = '/api/v3/ticker/price'; private readonly httpClient: HttpClient; + private _allSymbols: Set | undefined; constructor() { this.httpClient = new HttpClient(BinanceRatesProvider.baseUrl); } async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise { - const urlPath = `/api/v3/ticker/price?symbol=${baseCurrency}${quoteCurrency}`; + const symbol = `${baseCurrency}${quoteCurrency}`; + const allSymbols = await this.getAllSymbols(); + if (!allSymbols.has(symbol)) + return undefined; + + const urlPath = `${BinanceRatesProvider.priceUrlPath}?symbol=${symbol}`; const responseDto = await this.httpClient.request({ urlPath }, false); return this.mapRatesDtoToPrice(responseDto); @@ -28,4 +35,18 @@ export class BinanceRatesProvider implements RatesProvider { return new BigNumber(dto.price); } + + private async getAllSymbols(): Promise> { + if (!this._allSymbols) + this._allSymbols = new Set(await this.requestAllSymbols()); + + return this._allSymbols; + } + + private async requestAllSymbols(): Promise { + const urlPath = BinanceRatesProvider.priceUrlPath; + const responseDto = await this.httpClient.request({ urlPath }, false); + + return responseDto.map(dto => dto.symbol); + } } From 85c0c49f30e8a993e211218554d7cf2a31266195 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 22:02:41 +0300 Subject: [PATCH 13/19] Implement getAveragePrice --- .../ratesProvider/aggregatedRatesProvider.ts | 1 + .../mixedRatesProvider/mixedRatesProvider.ts | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/exchange/ratesProvider/aggregatedRatesProvider.ts b/src/exchange/ratesProvider/aggregatedRatesProvider.ts index 7bdec52b..bfbbe20b 100644 --- a/src/exchange/ratesProvider/aggregatedRatesProvider.ts +++ b/src/exchange/ratesProvider/aggregatedRatesProvider.ts @@ -4,5 +4,6 @@ import type { Currency } from '../../common'; export interface AggregatedRatesProvider { getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise; + getAveragePrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise; getAvailableProviders(): string[]; } diff --git a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts index 286d591c..5a54c79e 100644 --- a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts +++ b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts @@ -1,4 +1,4 @@ -import type BigNumber from 'bignumber.js'; +import BigNumber from 'bignumber.js'; import type { Currency } from '../../../common'; import type { AggregatedRatesProvider } from '../aggregatedRatesProvider'; @@ -9,6 +9,19 @@ export class MixedRatesProvider implements AggregatedRatesProvider { private readonly providersMap: Map ) { } + async getAveragePrice(baseCurrency: string, quoteCurrency: string): Promise { + const providers = this.getAvailableProviders(); + const pricePromises = providers.map(provider => this.getPrice(baseCurrency, quoteCurrency, provider)); + const pricePromiseResults = await Promise.allSettled(pricePromises); + + const prices: BigNumber[] = []; + for (const result of pricePromiseResults) + if (result.status === 'fulfilled' && result.value !== undefined) + prices.push(result.value); + + return prices.length ? BigNumber.sum(...prices).div(prices.length) : undefined; + } + async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise { let price = await this.getPriceCore(baseCurrency, quoteCurrency, provider); if (!price) { From 0a706ef3cb7a07a67b947fda6db72973aae4cd79 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 22:38:32 +0300 Subject: [PATCH 14/19] Refactor namings --- src/atomex/atomexContext.ts | 8 ++-- src/atomexBuilder/atomexBuilder.ts | 14 +++---- src/atomexBuilder/controlledAtomexContext.ts | 6 +-- src/exchange/index.ts | 6 +-- .../ratesProvider/aggregatedRatesProvider.ts | 9 ----- src/exchange/ratesProvider/atomex/index.ts | 1 - src/exchange/ratesProvider/binance/index.ts | 1 - src/exchange/ratesProvider/index.ts | 4 -- src/exchange/ratesProvider/kraken/index.ts | 1 - .../mixedRatesProvider/mixedRatesProvider.ts | 40 +++++++++---------- src/exchange/ratesProvider/ratesProvider.ts | 4 +- .../atomex/atomexRatesService.ts} | 4 +- src/exchange/ratesService/atomex/index.ts | 1 + .../binance/binanceRatesService.ts} | 10 ++--- .../binance/dtos.ts | 0 src/exchange/ratesService/binance/index.ts | 1 + .../binance/utils.ts | 0 src/exchange/ratesService/index.ts | 4 ++ .../kraken/dtos.ts | 0 src/exchange/ratesService/kraken/index.ts | 1 + .../kraken/krakenRatesService.ts} | 6 +-- src/exchange/ratesService/ratesService.ts | 7 ++++ 22 files changed, 63 insertions(+), 65 deletions(-) delete mode 100644 src/exchange/ratesProvider/aggregatedRatesProvider.ts delete mode 100644 src/exchange/ratesProvider/atomex/index.ts delete mode 100644 src/exchange/ratesProvider/binance/index.ts delete mode 100644 src/exchange/ratesProvider/kraken/index.ts rename src/exchange/{ratesProvider/atomex/atomexRatesProvider.ts => ratesService/atomex/atomexRatesService.ts} (86%) create mode 100644 src/exchange/ratesService/atomex/index.ts rename src/exchange/{ratesProvider/binance/binanceRatesProvider.ts => ratesService/binance/binanceRatesService.ts} (82%) rename src/exchange/{ratesProvider => ratesService}/binance/dtos.ts (100%) create mode 100644 src/exchange/ratesService/binance/index.ts rename src/exchange/{ratesProvider => ratesService}/binance/utils.ts (100%) create mode 100644 src/exchange/ratesService/index.ts rename src/exchange/{ratesProvider => ratesService}/kraken/dtos.ts (100%) create mode 100644 src/exchange/ratesService/kraken/index.ts rename src/exchange/{ratesProvider/kraken/krakenRatesProvider.ts => ratesService/kraken/krakenRatesService.ts} (84%) create mode 100644 src/exchange/ratesService/ratesService.ts diff --git a/src/atomex/atomexContext.ts b/src/atomex/atomexContext.ts index a8a1876a..367169d5 100644 --- a/src/atomex/atomexContext.ts +++ b/src/atomex/atomexContext.ts @@ -1,7 +1,7 @@ import type { AuthorizationManager } from '../authorization/index'; import type { WalletsManager, AtomexBlockchainProvider } from '../blockchain/index'; import type { AtomexNetwork, CurrenciesProvider } from '../common/index'; -import type { AggregatedRatesProvider, ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider } from '../exchange/index'; +import type { ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider, RatesProvider } from '../exchange/index'; import type { SwapManager, SwapService } from '../swaps/index'; export class AtomexContext { @@ -111,7 +111,7 @@ class AtomexContextProvidersSection { private _currenciesProvider: CurrenciesProvider | undefined; private _exchangeSymbolsProvider: ManagedExchangeSymbolsProvider | undefined; private _orderBookProvider: ManagedOrderBookProvider | undefined; - private _ratesProvider: AggregatedRatesProvider | undefined; + private _ratesProvider: RatesProvider | undefined; constructor(readonly context: AtomexContext) { } @@ -160,14 +160,14 @@ class AtomexContextProvidersSection { this._orderBookProvider = orderBookProvider; } - get ratesProvider(): AggregatedRatesProvider { + get ratesProvider(): RatesProvider { if (!this._ratesProvider) throw new AtomexComponentNotResolvedError('providers.ratesProvider'); return this._ratesProvider; } - private set ratesProvider(ratesProvider: AggregatedRatesProvider) { + private set ratesProvider(ratesProvider: RatesProvider) { this._ratesProvider = ratesProvider; } } diff --git a/src/atomexBuilder/atomexBuilder.ts b/src/atomexBuilder/atomexBuilder.ts index 24d5cc39..c28bb28b 100644 --- a/src/atomexBuilder/atomexBuilder.ts +++ b/src/atomexBuilder/atomexBuilder.ts @@ -5,8 +5,8 @@ import { AtomexBlockchainProvider, WalletsManager } from '../blockchain/index'; import type { DeepReadonly } from '../core/index'; import { createDefaultEthereumBlockchainOptions } from '../ethereum/index'; import { - AggregatedRatesProvider, AtomexRatesProvider, BinanceRatesProvider, ExchangeManager, InMemoryExchangeSymbolsProvider, - InMemoryOrderBookProvider, KrakenRatesProvider, MixedRatesProvider, RatesProvider + AtomexRatesService, BinanceRatesService, ExchangeManager, InMemoryExchangeSymbolsProvider, + InMemoryOrderBookProvider, KrakenRatesService, MixedRatesProvider, RatesProvider, RatesService } from '../exchange/index'; import { SwapManager } from '../swaps/swapManager'; import { createDefaultTezosBlockchainOptions } from '../tezos/index'; @@ -124,11 +124,11 @@ export class AtomexBuilder { }; } - protected createRatesProvider(): AggregatedRatesProvider { - return new MixedRatesProvider(new Map([ - ['binance', new BinanceRatesProvider()], - ['kraken', new KrakenRatesProvider()], - ['atomex', new AtomexRatesProvider(this.atomexContext.services.exchangeService)] + protected createRatesProvider(): RatesProvider { + return new MixedRatesProvider(new Map([ + ['binance', new BinanceRatesService()], + ['kraken', new KrakenRatesService()], + ['atomex', new AtomexRatesService(this.atomexContext.services.exchangeService)] ])); } } diff --git a/src/atomexBuilder/controlledAtomexContext.ts b/src/atomexBuilder/controlledAtomexContext.ts index 12c9b827..0877721c 100644 --- a/src/atomexBuilder/controlledAtomexContext.ts +++ b/src/atomexBuilder/controlledAtomexContext.ts @@ -2,7 +2,7 @@ import type { AuthorizationManager } from '../authorization/index'; import type { AtomexBlockchainProvider } from '../blockchain/atomexBlockchainProvider'; import type { WalletsManager } from '../blockchain/index'; import type { AtomexNetwork, CurrenciesProvider } from '../common/index'; -import type { AggregatedRatesProvider, ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider } from '../exchange/index'; +import type { ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider, RatesProvider } from '../exchange/index'; import type { SwapManager, SwapService } from '../swaps/index'; export interface ControlledAtomexContext { @@ -49,6 +49,6 @@ interface ControlledAtomexContextProvidersSection { get orderBookProvider(): ManagedOrderBookProvider; set orderBookProvider(value: ManagedOrderBookProvider); - get ratesProvider(): AggregatedRatesProvider; - set ratesProvider(value: AggregatedRatesProvider); + get ratesProvider(): RatesProvider; + set ratesProvider(value: RatesProvider); } diff --git a/src/exchange/index.ts b/src/exchange/index.ts index d1eb4615..c4cfc728 100644 --- a/src/exchange/index.ts +++ b/src/exchange/index.ts @@ -9,7 +9,5 @@ export type { ExchangeSymbolsProvider, ManagedExchangeSymbolsProvider } from './ export type { OrderBookProvider, ManagedOrderBookProvider } from './orderBookProvider/index'; export type { ExchangeService, ExchangeServiceEvents } from './exchangeService'; -export { - type RatesProvider, type AggregatedRatesProvider, - BinanceRatesProvider, KrakenRatesProvider, MixedRatesProvider, AtomexRatesProvider -} from './ratesProvider/index'; +export { type RatesProvider, MixedRatesProvider } from './ratesProvider/index'; +export { type RatesService, AtomexRatesService, BinanceRatesService, KrakenRatesService } from './ratesService/index'; diff --git a/src/exchange/ratesProvider/aggregatedRatesProvider.ts b/src/exchange/ratesProvider/aggregatedRatesProvider.ts deleted file mode 100644 index bfbbe20b..00000000 --- a/src/exchange/ratesProvider/aggregatedRatesProvider.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type BigNumber from 'bignumber.js'; - -import type { Currency } from '../../common'; - -export interface AggregatedRatesProvider { - getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise; - getAveragePrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise; - getAvailableProviders(): string[]; -} diff --git a/src/exchange/ratesProvider/atomex/index.ts b/src/exchange/ratesProvider/atomex/index.ts deleted file mode 100644 index 9a5b4b7b..00000000 --- a/src/exchange/ratesProvider/atomex/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { AtomexRatesProvider } from './atomexRatesProvider'; diff --git a/src/exchange/ratesProvider/binance/index.ts b/src/exchange/ratesProvider/binance/index.ts deleted file mode 100644 index e915cbb9..00000000 --- a/src/exchange/ratesProvider/binance/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { BinanceRatesProvider } from './binanceRatesProvider'; diff --git a/src/exchange/ratesProvider/index.ts b/src/exchange/ratesProvider/index.ts index b9e153e7..3c295207 100644 --- a/src/exchange/ratesProvider/index.ts +++ b/src/exchange/ratesProvider/index.ts @@ -1,6 +1,2 @@ export type { RatesProvider } from './ratesProvider'; -export type { AggregatedRatesProvider } from './aggregatedRatesProvider'; -export { AtomexRatesProvider } from './atomex/index'; -export { BinanceRatesProvider } from './binance/index'; -export { KrakenRatesProvider } from './kraken/index'; export { MixedRatesProvider } from './mixedRatesProvider/index'; diff --git a/src/exchange/ratesProvider/kraken/index.ts b/src/exchange/ratesProvider/kraken/index.ts deleted file mode 100644 index 882bb11d..00000000 --- a/src/exchange/ratesProvider/kraken/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { KrakenRatesProvider } from './krakenRatesProvider'; diff --git a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts index 5a54c79e..1dd03b5a 100644 --- a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts +++ b/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts @@ -1,17 +1,17 @@ import BigNumber from 'bignumber.js'; import type { Currency } from '../../../common'; -import type { AggregatedRatesProvider } from '../aggregatedRatesProvider'; +import type { RatesService } from '../../ratesService/index'; import type { RatesProvider } from '../ratesProvider'; -export class MixedRatesProvider implements AggregatedRatesProvider { +export class MixedRatesProvider implements RatesProvider { constructor( - private readonly providersMap: Map + private readonly servicesMap: Map ) { } async getAveragePrice(baseCurrency: string, quoteCurrency: string): Promise { - const providers = this.getAvailableProviders(); - const pricePromises = providers.map(provider => this.getPrice(baseCurrency, quoteCurrency, provider)); + const services = this.getAvailableServices(); + const pricePromises = services.map(service => this.getPrice(baseCurrency, quoteCurrency, service)); const pricePromiseResults = await Promise.allSettled(pricePromises); const prices: BigNumber[] = []; @@ -22,10 +22,10 @@ export class MixedRatesProvider implements AggregatedRatesProvider { return prices.length ? BigNumber.sum(...prices).div(prices.length) : undefined; } - async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise { - let price = await this.getPriceCore(baseCurrency, quoteCurrency, provider); + async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], service?: string): Promise { + let price = await this.getPriceCore(baseCurrency, quoteCurrency, service); if (!price) { - const reversedPrice = await this.getPriceCore(quoteCurrency, baseCurrency, provider); + const reversedPrice = await this.getPriceCore(quoteCurrency, baseCurrency, service); if (reversedPrice) price = reversedPrice.pow(-1); } @@ -33,13 +33,13 @@ export class MixedRatesProvider implements AggregatedRatesProvider { return price; } - getAvailableProviders(): string[] { - return [...this.providersMap.keys()]; + getAvailableServices(): string[] { + return [...this.servicesMap.keys()]; } - private async getPriceCore(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise { - const providers = this.getSelectedProviders(provider); - const pricePromises = providers.map(p => p.getPrice(baseCurrency, quoteCurrency)); + private async getPriceCore(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], service?: string): Promise { + const services = this.getSelectedServices(service); + const pricePromises = services.map(service => service.getPrice(baseCurrency, quoteCurrency)); const pricePromiseResults = await Promise.allSettled(pricePromises); for (const result of pricePromiseResults) @@ -49,14 +49,14 @@ export class MixedRatesProvider implements AggregatedRatesProvider { return undefined; } - private getSelectedProviders(provider?: string): RatesProvider[] { - if (!provider) - return [...this.providersMap.values()]; + private getSelectedServices(service?: string): RatesService[] { + if (!service) + return [...this.servicesMap.values()]; - const selectedProvider = this.providersMap.get(provider); - if (!selectedProvider) - throw new Error(`Provider not found for key: ${provider}`); + const selectedService = this.servicesMap.get(service); + if (!selectedService) + throw new Error(`Service not found for key: ${service}`); - return [selectedProvider]; + return [selectedService]; } } diff --git a/src/exchange/ratesProvider/ratesProvider.ts b/src/exchange/ratesProvider/ratesProvider.ts index 40afb082..832acb13 100644 --- a/src/exchange/ratesProvider/ratesProvider.ts +++ b/src/exchange/ratesProvider/ratesProvider.ts @@ -3,5 +3,7 @@ import type BigNumber from 'bignumber.js'; import type { Currency } from '../../common'; export interface RatesProvider { - getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise; + getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], service?: string): Promise; + getAveragePrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise; + getAvailableServices(): string[]; } diff --git a/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts b/src/exchange/ratesService/atomex/atomexRatesService.ts similarity index 86% rename from src/exchange/ratesProvider/atomex/atomexRatesProvider.ts rename to src/exchange/ratesService/atomex/atomexRatesService.ts index 3e8bc7a1..d310f34a 100644 --- a/src/exchange/ratesProvider/atomex/atomexRatesProvider.ts +++ b/src/exchange/ratesService/atomex/atomexRatesService.ts @@ -3,9 +3,9 @@ import type BigNumber from 'bignumber.js'; import type { Currency } from '../../../common/index'; import type { ExchangeService } from '../../exchangeService'; import type { Quote } from '../../models/index'; -import type { RatesProvider } from '../ratesProvider'; +import type { RatesService } from '../ratesService'; -export class AtomexRatesProvider implements RatesProvider { +export class AtomexRatesService implements RatesService { constructor( private readonly exchangeService: ExchangeService ) { } diff --git a/src/exchange/ratesService/atomex/index.ts b/src/exchange/ratesService/atomex/index.ts new file mode 100644 index 00000000..716f88b4 --- /dev/null +++ b/src/exchange/ratesService/atomex/index.ts @@ -0,0 +1 @@ +export { AtomexRatesService } from './atomexRatesService'; diff --git a/src/exchange/ratesProvider/binance/binanceRatesProvider.ts b/src/exchange/ratesService/binance/binanceRatesService.ts similarity index 82% rename from src/exchange/ratesProvider/binance/binanceRatesProvider.ts rename to src/exchange/ratesService/binance/binanceRatesService.ts index 58ad1d46..8de36e3b 100644 --- a/src/exchange/ratesProvider/binance/binanceRatesProvider.ts +++ b/src/exchange/ratesService/binance/binanceRatesService.ts @@ -2,11 +2,11 @@ import BigNumber from 'bignumber.js'; import type { Currency } from '../../../common'; import { HttpClient } from '../../../core'; -import type { RatesProvider } from '../ratesProvider'; +import type { RatesService } from '../ratesService'; import type { BinanceErrorDto, BinanceRatesDto } from './dtos'; import { isErrorDto } from './utils'; -export class BinanceRatesProvider implements RatesProvider { +export class BinanceRatesService implements RatesService { private static readonly baseUrl = 'https://www.binance.com'; private static readonly priceUrlPath = '/api/v3/ticker/price'; @@ -14,7 +14,7 @@ export class BinanceRatesProvider implements RatesProvider { private _allSymbols: Set | undefined; constructor() { - this.httpClient = new HttpClient(BinanceRatesProvider.baseUrl); + this.httpClient = new HttpClient(BinanceRatesService.baseUrl); } async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise { @@ -23,7 +23,7 @@ export class BinanceRatesProvider implements RatesProvider { if (!allSymbols.has(symbol)) return undefined; - const urlPath = `${BinanceRatesProvider.priceUrlPath}?symbol=${symbol}`; + const urlPath = `${BinanceRatesService.priceUrlPath}?symbol=${symbol}`; const responseDto = await this.httpClient.request({ urlPath }, false); return this.mapRatesDtoToPrice(responseDto); @@ -44,7 +44,7 @@ export class BinanceRatesProvider implements RatesProvider { } private async requestAllSymbols(): Promise { - const urlPath = BinanceRatesProvider.priceUrlPath; + const urlPath = BinanceRatesService.priceUrlPath; const responseDto = await this.httpClient.request({ urlPath }, false); return responseDto.map(dto => dto.symbol); diff --git a/src/exchange/ratesProvider/binance/dtos.ts b/src/exchange/ratesService/binance/dtos.ts similarity index 100% rename from src/exchange/ratesProvider/binance/dtos.ts rename to src/exchange/ratesService/binance/dtos.ts diff --git a/src/exchange/ratesService/binance/index.ts b/src/exchange/ratesService/binance/index.ts new file mode 100644 index 00000000..e91280f0 --- /dev/null +++ b/src/exchange/ratesService/binance/index.ts @@ -0,0 +1 @@ +export { BinanceRatesService } from './binanceRatesService'; diff --git a/src/exchange/ratesProvider/binance/utils.ts b/src/exchange/ratesService/binance/utils.ts similarity index 100% rename from src/exchange/ratesProvider/binance/utils.ts rename to src/exchange/ratesService/binance/utils.ts diff --git a/src/exchange/ratesService/index.ts b/src/exchange/ratesService/index.ts new file mode 100644 index 00000000..ae192289 --- /dev/null +++ b/src/exchange/ratesService/index.ts @@ -0,0 +1,4 @@ +export type { RatesService } from './ratesService'; +export { AtomexRatesService } from './atomex/index'; +export { BinanceRatesService } from './binance/index'; +export { KrakenRatesService } from './kraken/index'; diff --git a/src/exchange/ratesProvider/kraken/dtos.ts b/src/exchange/ratesService/kraken/dtos.ts similarity index 100% rename from src/exchange/ratesProvider/kraken/dtos.ts rename to src/exchange/ratesService/kraken/dtos.ts diff --git a/src/exchange/ratesService/kraken/index.ts b/src/exchange/ratesService/kraken/index.ts new file mode 100644 index 00000000..9d3a4d52 --- /dev/null +++ b/src/exchange/ratesService/kraken/index.ts @@ -0,0 +1 @@ +export { KrakenRatesService } from './krakenRatesService'; diff --git a/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts b/src/exchange/ratesService/kraken/krakenRatesService.ts similarity index 84% rename from src/exchange/ratesProvider/kraken/krakenRatesProvider.ts rename to src/exchange/ratesService/kraken/krakenRatesService.ts index c8411fe8..f0f2c3eb 100644 --- a/src/exchange/ratesProvider/kraken/krakenRatesProvider.ts +++ b/src/exchange/ratesService/kraken/krakenRatesService.ts @@ -2,16 +2,16 @@ import BigNumber from 'bignumber.js'; import type { Currency } from '../../../common'; import { HttpClient } from '../../../core'; -import type { RatesProvider } from '../ratesProvider'; +import type { RatesService } from '../ratesService'; import type { KrakenRatesDto } from './dtos'; -export class KrakenRatesProvider implements RatesProvider { +export class KrakenRatesService implements RatesService { private static readonly baseUrl = 'https://api.kraken.com'; private readonly httpClient: HttpClient; constructor() { - this.httpClient = new HttpClient(KrakenRatesProvider.baseUrl); + this.httpClient = new HttpClient(KrakenRatesService.baseUrl); } async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise { diff --git a/src/exchange/ratesService/ratesService.ts b/src/exchange/ratesService/ratesService.ts new file mode 100644 index 00000000..943c13ec --- /dev/null +++ b/src/exchange/ratesService/ratesService.ts @@ -0,0 +1,7 @@ +import type BigNumber from 'bignumber.js'; + +import type { Currency } from '../../common'; + +export interface RatesService { + getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise; +} From 4568073692efe71c138428aa4a677b65b0855bfd Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 22:59:00 +0300 Subject: [PATCH 15/19] Add convertCurrency method --- src/atomex/atomex.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/atomex/atomex.ts b/src/atomex/atomex.ts index b8edf180..bc7ee7c0 100644 --- a/src/atomex/atomex.ts +++ b/src/atomex/atomex.ts @@ -1,8 +1,11 @@ +import BigNumber from 'bignumber.js'; + import type { AuthorizationManager } from '../authorization/index'; import type { WalletsManager } from '../blockchain/index'; import type { AtomexService, Currency } from '../common/index'; import type { ExchangeManager } from '../exchange/exchangeManager'; import type { Swap, SwapManager } from '../swaps/index'; +import { toFixedBigNumber } from '../utils/converters'; import type { AtomexContext } from './atomexContext'; import { SwapOperationCompleteStage, AtomexOptions, @@ -66,7 +69,7 @@ export class Atomex implements AtomexService { this.atomexContext.providers.blockchainProvider.addBlockchain(blockchain, blockchainOptions); } - getCurrency(currencyId: Currency['id']) { + getCurrency(currencyId: Currency['id']): Currency | undefined { return this.atomexContext.providers.currenciesProvider.getCurrency(currencyId); } @@ -93,4 +96,16 @@ export class Atomex implements AtomexService { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return swaps.length === 1 ? swaps[0]! : (swaps as readonly Swap[]); } + + async convertCurrency(from: Currency['id'], to: Currency['id'], inAmount: BigNumber.Value): Promise { + const price = await this.atomexContext.providers.ratesProvider.getAveragePrice(from, to); + if (!price) + return undefined; + + const inAmountBigNumber = BigNumber.isBigNumber(inAmount) ? inAmount : new BigNumber(inAmount); + const outAmount = inAmountBigNumber.multipliedBy(price); + const toCurrency = this.getCurrency(to); + + return toCurrency ? toFixedBigNumber(outAmount, toCurrency.decimals) : outAmount; + } } From 15fdd930ab7058fa724d872aaa968bc60eae7856 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 23 Aug 2022 23:04:32 +0300 Subject: [PATCH 16/19] Refactor --- src/atomex/atomex.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/atomex/atomex.ts b/src/atomex/atomex.ts index bc7ee7c0..67ca0cd4 100644 --- a/src/atomex/atomex.ts +++ b/src/atomex/atomex.ts @@ -97,15 +97,15 @@ export class Atomex implements AtomexService { return swaps.length === 1 ? swaps[0]! : (swaps as readonly Swap[]); } - async convertCurrency(from: Currency['id'], to: Currency['id'], inAmount: BigNumber.Value): Promise { - const price = await this.atomexContext.providers.ratesProvider.getAveragePrice(from, to); + async convertCurrency(fromAmount: BigNumber.Value, fromCurrency: Currency['id'], toCurrency: Currency['id']): Promise { + const price = await this.atomexContext.providers.ratesProvider.getAveragePrice(fromCurrency, toCurrency); if (!price) return undefined; - const inAmountBigNumber = BigNumber.isBigNumber(inAmount) ? inAmount : new BigNumber(inAmount); + const inAmountBigNumber = BigNumber.isBigNumber(fromAmount) ? fromAmount : new BigNumber(fromAmount); const outAmount = inAmountBigNumber.multipliedBy(price); - const toCurrency = this.getCurrency(to); + const toCurrencyInfo = this.getCurrency(toCurrency); - return toCurrency ? toFixedBigNumber(outAmount, toCurrency.decimals) : outAmount; + return toCurrencyInfo ? toFixedBigNumber(outAmount, toCurrencyInfo.decimals) : outAmount; } } From 3f042bcbab9de4d37907eac75bf7b88d2ae4775e Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Wed, 24 Aug 2022 21:57:44 +0300 Subject: [PATCH 17/19] Rename ratesProvider to priceManager --- src/atomex/atomex.ts | 2 +- src/atomex/atomexContext.ts | 26 +++++++++---------- src/atomexBuilder/atomexBuilder.ts | 8 +++--- src/atomexBuilder/controlledAtomexContext.ts | 8 +++--- src/exchange/index.ts | 2 +- src/exchange/priceManager/index.ts | 2 ++ .../priceManager/mixedPriceManager/index.ts | 1 + .../mixedPriceManager/mixedPriceManager.ts} | 8 +++--- .../priceManager.ts} | 4 +-- src/exchange/ratesProvider/index.ts | 2 -- .../ratesProvider/mixedRatesProvider/index.ts | 1 - 11 files changed, 32 insertions(+), 32 deletions(-) create mode 100644 src/exchange/priceManager/index.ts create mode 100644 src/exchange/priceManager/mixedPriceManager/index.ts rename src/exchange/{ratesProvider/mixedRatesProvider/mixedRatesProvider.ts => priceManager/mixedPriceManager/mixedPriceManager.ts} (91%) rename src/exchange/{ratesProvider/ratesProvider.ts => priceManager/priceManager.ts} (82%) delete mode 100644 src/exchange/ratesProvider/index.ts delete mode 100644 src/exchange/ratesProvider/mixedRatesProvider/index.ts diff --git a/src/atomex/atomex.ts b/src/atomex/atomex.ts index 67ca0cd4..79106c0b 100644 --- a/src/atomex/atomex.ts +++ b/src/atomex/atomex.ts @@ -98,7 +98,7 @@ export class Atomex implements AtomexService { } async convertCurrency(fromAmount: BigNumber.Value, fromCurrency: Currency['id'], toCurrency: Currency['id']): Promise { - const price = await this.atomexContext.providers.ratesProvider.getAveragePrice(fromCurrency, toCurrency); + const price = await this.atomexContext.managers.priceManager.getAveragePrice(fromCurrency, toCurrency); if (!price) return undefined; diff --git a/src/atomex/atomexContext.ts b/src/atomex/atomexContext.ts index 367169d5..17be1cd7 100644 --- a/src/atomex/atomexContext.ts +++ b/src/atomex/atomexContext.ts @@ -1,7 +1,7 @@ import type { AuthorizationManager } from '../authorization/index'; import type { WalletsManager, AtomexBlockchainProvider } from '../blockchain/index'; import type { AtomexNetwork, CurrenciesProvider } from '../common/index'; -import type { ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider, RatesProvider } from '../exchange/index'; +import type { ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider, PriceManager } from '../exchange/index'; import type { SwapManager, SwapService } from '../swaps/index'; export class AtomexContext { @@ -27,6 +27,7 @@ class AtomexContextManagersSection { private _authorizationManager: AuthorizationManager | undefined; private _exchangeManager: ExchangeManager | undefined; private _swapManager: SwapManager | undefined; + private _priceManager: PriceManager | undefined; constructor(readonly context: AtomexContext) { } @@ -74,6 +75,17 @@ class AtomexContextManagersSection { private set swapManager(swapManager: SwapManager) { this._swapManager = swapManager; } + + get priceManager(): PriceManager { + if (!this._priceManager) + throw new AtomexComponentNotResolvedError('managers.priceManager'); + + return this._priceManager; + } + + private set priceManager(priceManager: PriceManager) { + this._priceManager = priceManager; + } } class AtomexContextServicesSection { @@ -111,7 +123,6 @@ class AtomexContextProvidersSection { private _currenciesProvider: CurrenciesProvider | undefined; private _exchangeSymbolsProvider: ManagedExchangeSymbolsProvider | undefined; private _orderBookProvider: ManagedOrderBookProvider | undefined; - private _ratesProvider: RatesProvider | undefined; constructor(readonly context: AtomexContext) { } @@ -159,17 +170,6 @@ class AtomexContextProvidersSection { private set orderBookProvider(orderBookProvider: ManagedOrderBookProvider) { this._orderBookProvider = orderBookProvider; } - - get ratesProvider(): RatesProvider { - if (!this._ratesProvider) - throw new AtomexComponentNotResolvedError('providers.ratesProvider'); - - return this._ratesProvider; - } - - private set ratesProvider(ratesProvider: RatesProvider) { - this._ratesProvider = ratesProvider; - } } export class AtomexComponentNotResolvedError extends Error { diff --git a/src/atomexBuilder/atomexBuilder.ts b/src/atomexBuilder/atomexBuilder.ts index c28bb28b..8a08d0a3 100644 --- a/src/atomexBuilder/atomexBuilder.ts +++ b/src/atomexBuilder/atomexBuilder.ts @@ -6,7 +6,7 @@ import type { DeepReadonly } from '../core/index'; import { createDefaultEthereumBlockchainOptions } from '../ethereum/index'; import { AtomexRatesService, BinanceRatesService, ExchangeManager, InMemoryExchangeSymbolsProvider, - InMemoryOrderBookProvider, KrakenRatesService, MixedRatesProvider, RatesProvider, RatesService + InMemoryOrderBookProvider, KrakenRatesService, PriceManager, MixedPriceManager, RatesService } from '../exchange/index'; import { SwapManager } from '../swaps/swapManager'; import { createDefaultTezosBlockchainOptions } from '../tezos/index'; @@ -60,7 +60,7 @@ export class AtomexBuilder { this.controlledAtomexContext.services.swapService = atomexClient; this.controlledAtomexContext.managers.exchangeManager = this.createExchangeManager(); this.controlledAtomexContext.managers.swapManager = this.createSwapManager(); - this.controlledAtomexContext.providers.ratesProvider = this.createRatesProvider(); + this.controlledAtomexContext.managers.priceManager = this.createPriceManager(); const blockchains = this.createDefaultBlockchainOptions(); return new Atomex({ @@ -124,8 +124,8 @@ export class AtomexBuilder { }; } - protected createRatesProvider(): RatesProvider { - return new MixedRatesProvider(new Map([ + protected createPriceManager(): PriceManager { + return new MixedPriceManager(new Map([ ['binance', new BinanceRatesService()], ['kraken', new KrakenRatesService()], ['atomex', new AtomexRatesService(this.atomexContext.services.exchangeService)] diff --git a/src/atomexBuilder/controlledAtomexContext.ts b/src/atomexBuilder/controlledAtomexContext.ts index 0877721c..6bc2c291 100644 --- a/src/atomexBuilder/controlledAtomexContext.ts +++ b/src/atomexBuilder/controlledAtomexContext.ts @@ -2,7 +2,7 @@ import type { AuthorizationManager } from '../authorization/index'; import type { AtomexBlockchainProvider } from '../blockchain/atomexBlockchainProvider'; import type { WalletsManager } from '../blockchain/index'; import type { AtomexNetwork, CurrenciesProvider } from '../common/index'; -import type { ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider, RatesProvider } from '../exchange/index'; +import type { ExchangeManager, ExchangeService, ManagedExchangeSymbolsProvider, ManagedOrderBookProvider, PriceManager } from '../exchange/index'; import type { SwapManager, SwapService } from '../swaps/index'; export interface ControlledAtomexContext { @@ -26,6 +26,9 @@ interface ControlledAtomexContextManagersSection { get swapManager(): SwapManager; set swapManager(value: SwapManager); + + get priceManager(): PriceManager; + set priceManager(value: PriceManager); } interface ControlledAtomexContextServicesSection { @@ -48,7 +51,4 @@ interface ControlledAtomexContextProvidersSection { get orderBookProvider(): ManagedOrderBookProvider; set orderBookProvider(value: ManagedOrderBookProvider); - - get ratesProvider(): RatesProvider; - set ratesProvider(value: RatesProvider); } diff --git a/src/exchange/index.ts b/src/exchange/index.ts index c4cfc728..b6707011 100644 --- a/src/exchange/index.ts +++ b/src/exchange/index.ts @@ -9,5 +9,5 @@ export type { ExchangeSymbolsProvider, ManagedExchangeSymbolsProvider } from './ export type { OrderBookProvider, ManagedOrderBookProvider } from './orderBookProvider/index'; export type { ExchangeService, ExchangeServiceEvents } from './exchangeService'; -export { type RatesProvider, MixedRatesProvider } from './ratesProvider/index'; +export { type PriceManager, MixedPriceManager } from './priceManager/index'; export { type RatesService, AtomexRatesService, BinanceRatesService, KrakenRatesService } from './ratesService/index'; diff --git a/src/exchange/priceManager/index.ts b/src/exchange/priceManager/index.ts new file mode 100644 index 00000000..b7af68c2 --- /dev/null +++ b/src/exchange/priceManager/index.ts @@ -0,0 +1,2 @@ +export type { PriceManager } from './priceManager'; +export { MixedPriceManager } from './mixedPriceManager/index'; diff --git a/src/exchange/priceManager/mixedPriceManager/index.ts b/src/exchange/priceManager/mixedPriceManager/index.ts new file mode 100644 index 00000000..5f9ff99b --- /dev/null +++ b/src/exchange/priceManager/mixedPriceManager/index.ts @@ -0,0 +1 @@ +export { MixedPriceManager } from './mixedPriceManager'; diff --git a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts b/src/exchange/priceManager/mixedPriceManager/mixedPriceManager.ts similarity index 91% rename from src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts rename to src/exchange/priceManager/mixedPriceManager/mixedPriceManager.ts index 1dd03b5a..138aee39 100644 --- a/src/exchange/ratesProvider/mixedRatesProvider/mixedRatesProvider.ts +++ b/src/exchange/priceManager/mixedPriceManager/mixedPriceManager.ts @@ -2,15 +2,15 @@ import BigNumber from 'bignumber.js'; import type { Currency } from '../../../common'; import type { RatesService } from '../../ratesService/index'; -import type { RatesProvider } from '../ratesProvider'; +import type { PriceManager } from '../priceManager'; -export class MixedRatesProvider implements RatesProvider { +export class MixedPriceManager implements PriceManager { constructor( private readonly servicesMap: Map ) { } async getAveragePrice(baseCurrency: string, quoteCurrency: string): Promise { - const services = this.getAvailableServices(); + const services = this.getAvailableProviders(); const pricePromises = services.map(service => this.getPrice(baseCurrency, quoteCurrency, service)); const pricePromiseResults = await Promise.allSettled(pricePromises); @@ -33,7 +33,7 @@ export class MixedRatesProvider implements RatesProvider { return price; } - getAvailableServices(): string[] { + getAvailableProviders(): string[] { return [...this.servicesMap.keys()]; } diff --git a/src/exchange/ratesProvider/ratesProvider.ts b/src/exchange/priceManager/priceManager.ts similarity index 82% rename from src/exchange/ratesProvider/ratesProvider.ts rename to src/exchange/priceManager/priceManager.ts index 832acb13..a2ff85a2 100644 --- a/src/exchange/ratesProvider/ratesProvider.ts +++ b/src/exchange/priceManager/priceManager.ts @@ -2,8 +2,8 @@ import type BigNumber from 'bignumber.js'; import type { Currency } from '../../common'; -export interface RatesProvider { +export interface PriceManager { getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], service?: string): Promise; getAveragePrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise; - getAvailableServices(): string[]; + getAvailableProviders(): string[]; } diff --git a/src/exchange/ratesProvider/index.ts b/src/exchange/ratesProvider/index.ts deleted file mode 100644 index 3c295207..00000000 --- a/src/exchange/ratesProvider/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type { RatesProvider } from './ratesProvider'; -export { MixedRatesProvider } from './mixedRatesProvider/index'; diff --git a/src/exchange/ratesProvider/mixedRatesProvider/index.ts b/src/exchange/ratesProvider/mixedRatesProvider/index.ts deleted file mode 100644 index 4085da3f..00000000 --- a/src/exchange/ratesProvider/mixedRatesProvider/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { MixedRatesProvider } from './mixedRatesProvider'; From d9976cd9e4511a3c77ec896bf4f779e497a38d7e Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Wed, 24 Aug 2022 22:10:39 +0300 Subject: [PATCH 18/19] Rename ratesService to priceProvider --- src/atomexBuilder/atomexBuilder.ts | 12 +++---- src/exchange/index.ts | 2 +- .../mixedPriceManager/mixedPriceManager.ts | 36 +++++++++---------- src/exchange/priceManager/priceManager.ts | 2 +- .../atomex/atomexPriceProvider.ts} | 4 +-- src/exchange/priceProvider/atomex/index.ts | 1 + .../binance/binancePriceProvider.ts} | 10 +++--- .../binance/dtos.ts | 0 src/exchange/priceProvider/binance/index.ts | 1 + .../binance/utils.ts | 0 src/exchange/priceProvider/index.ts | 4 +++ .../kraken/dtos.ts | 0 src/exchange/priceProvider/kraken/index.ts | 1 + .../kraken/krakenPriceProvider.ts} | 6 ++-- .../priceProvider.ts} | 2 +- src/exchange/ratesService/atomex/index.ts | 1 - src/exchange/ratesService/binance/index.ts | 1 - src/exchange/ratesService/index.ts | 4 --- src/exchange/ratesService/kraken/index.ts | 1 - 19 files changed, 44 insertions(+), 44 deletions(-) rename src/exchange/{ratesService/atomex/atomexRatesService.ts => priceProvider/atomex/atomexPriceProvider.ts} (86%) create mode 100644 src/exchange/priceProvider/atomex/index.ts rename src/exchange/{ratesService/binance/binanceRatesService.ts => priceProvider/binance/binancePriceProvider.ts} (82%) rename src/exchange/{ratesService => priceProvider}/binance/dtos.ts (100%) create mode 100644 src/exchange/priceProvider/binance/index.ts rename src/exchange/{ratesService => priceProvider}/binance/utils.ts (100%) create mode 100644 src/exchange/priceProvider/index.ts rename src/exchange/{ratesService => priceProvider}/kraken/dtos.ts (100%) create mode 100644 src/exchange/priceProvider/kraken/index.ts rename src/exchange/{ratesService/kraken/krakenRatesService.ts => priceProvider/kraken/krakenPriceProvider.ts} (84%) rename src/exchange/{ratesService/ratesService.ts => priceProvider/priceProvider.ts} (85%) delete mode 100644 src/exchange/ratesService/atomex/index.ts delete mode 100644 src/exchange/ratesService/binance/index.ts delete mode 100644 src/exchange/ratesService/index.ts delete mode 100644 src/exchange/ratesService/kraken/index.ts diff --git a/src/atomexBuilder/atomexBuilder.ts b/src/atomexBuilder/atomexBuilder.ts index 8a08d0a3..20b9dca0 100644 --- a/src/atomexBuilder/atomexBuilder.ts +++ b/src/atomexBuilder/atomexBuilder.ts @@ -5,8 +5,8 @@ import { AtomexBlockchainProvider, WalletsManager } from '../blockchain/index'; import type { DeepReadonly } from '../core/index'; import { createDefaultEthereumBlockchainOptions } from '../ethereum/index'; import { - AtomexRatesService, BinanceRatesService, ExchangeManager, InMemoryExchangeSymbolsProvider, - InMemoryOrderBookProvider, KrakenRatesService, PriceManager, MixedPriceManager, RatesService + AtomexPriceProvider, BinancePriceProvider, ExchangeManager, InMemoryExchangeSymbolsProvider, + InMemoryOrderBookProvider, KrakenPriceProvider, PriceManager, MixedPriceManager, PriceProvider } from '../exchange/index'; import { SwapManager } from '../swaps/swapManager'; import { createDefaultTezosBlockchainOptions } from '../tezos/index'; @@ -125,10 +125,10 @@ export class AtomexBuilder { } protected createPriceManager(): PriceManager { - return new MixedPriceManager(new Map([ - ['binance', new BinanceRatesService()], - ['kraken', new KrakenRatesService()], - ['atomex', new AtomexRatesService(this.atomexContext.services.exchangeService)] + return new MixedPriceManager(new Map([ + ['binance', new BinancePriceProvider()], + ['kraken', new KrakenPriceProvider()], + ['atomex', new AtomexPriceProvider(this.atomexContext.services.exchangeService)] ])); } } diff --git a/src/exchange/index.ts b/src/exchange/index.ts index b6707011..aee027d0 100644 --- a/src/exchange/index.ts +++ b/src/exchange/index.ts @@ -10,4 +10,4 @@ export type { OrderBookProvider, ManagedOrderBookProvider } from './orderBookPro export type { ExchangeService, ExchangeServiceEvents } from './exchangeService'; export { type PriceManager, MixedPriceManager } from './priceManager/index'; -export { type RatesService, AtomexRatesService, BinanceRatesService, KrakenRatesService } from './ratesService/index'; +export { type PriceProvider, AtomexPriceProvider, BinancePriceProvider, KrakenPriceProvider } from './priceProvider/index'; diff --git a/src/exchange/priceManager/mixedPriceManager/mixedPriceManager.ts b/src/exchange/priceManager/mixedPriceManager/mixedPriceManager.ts index 138aee39..1c3fb2a9 100644 --- a/src/exchange/priceManager/mixedPriceManager/mixedPriceManager.ts +++ b/src/exchange/priceManager/mixedPriceManager/mixedPriceManager.ts @@ -1,17 +1,17 @@ import BigNumber from 'bignumber.js'; import type { Currency } from '../../../common'; -import type { RatesService } from '../../ratesService/index'; +import type { PriceProvider } from '../../priceProvider/index'; import type { PriceManager } from '../priceManager'; export class MixedPriceManager implements PriceManager { constructor( - private readonly servicesMap: Map + private readonly providersMap: Map ) { } async getAveragePrice(baseCurrency: string, quoteCurrency: string): Promise { - const services = this.getAvailableProviders(); - const pricePromises = services.map(service => this.getPrice(baseCurrency, quoteCurrency, service)); + const providers = this.getAvailableProviders(); + const pricePromises = providers.map(provider => this.getPrice(baseCurrency, quoteCurrency, provider)); const pricePromiseResults = await Promise.allSettled(pricePromises); const prices: BigNumber[] = []; @@ -22,10 +22,10 @@ export class MixedPriceManager implements PriceManager { return prices.length ? BigNumber.sum(...prices).div(prices.length) : undefined; } - async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], service?: string): Promise { - let price = await this.getPriceCore(baseCurrency, quoteCurrency, service); + async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise { + let price = await this.getPriceCore(baseCurrency, quoteCurrency, provider); if (!price) { - const reversedPrice = await this.getPriceCore(quoteCurrency, baseCurrency, service); + const reversedPrice = await this.getPriceCore(quoteCurrency, baseCurrency, provider); if (reversedPrice) price = reversedPrice.pow(-1); } @@ -34,12 +34,12 @@ export class MixedPriceManager implements PriceManager { } getAvailableProviders(): string[] { - return [...this.servicesMap.keys()]; + return [...this.providersMap.keys()]; } - private async getPriceCore(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], service?: string): Promise { - const services = this.getSelectedServices(service); - const pricePromises = services.map(service => service.getPrice(baseCurrency, quoteCurrency)); + private async getPriceCore(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise { + const providers = this.getSelectedProviders(provider); + const pricePromises = providers.map(provider => provider.getPrice(baseCurrency, quoteCurrency)); const pricePromiseResults = await Promise.allSettled(pricePromises); for (const result of pricePromiseResults) @@ -49,14 +49,14 @@ export class MixedPriceManager implements PriceManager { return undefined; } - private getSelectedServices(service?: string): RatesService[] { - if (!service) - return [...this.servicesMap.values()]; + private getSelectedProviders(provider?: string): PriceProvider[] { + if (!provider) + return [...this.providersMap.values()]; - const selectedService = this.servicesMap.get(service); - if (!selectedService) - throw new Error(`Service not found for key: ${service}`); + const selectedProvider = this.providersMap.get(provider); + if (!selectedProvider) + throw new Error(`Provider not found for key: ${provider}`); - return [selectedService]; + return [selectedProvider]; } } diff --git a/src/exchange/priceManager/priceManager.ts b/src/exchange/priceManager/priceManager.ts index a2ff85a2..5af2f3d5 100644 --- a/src/exchange/priceManager/priceManager.ts +++ b/src/exchange/priceManager/priceManager.ts @@ -3,7 +3,7 @@ import type BigNumber from 'bignumber.js'; import type { Currency } from '../../common'; export interface PriceManager { - getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], service?: string): Promise; + getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise; getAveragePrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise; getAvailableProviders(): string[]; } diff --git a/src/exchange/ratesService/atomex/atomexRatesService.ts b/src/exchange/priceProvider/atomex/atomexPriceProvider.ts similarity index 86% rename from src/exchange/ratesService/atomex/atomexRatesService.ts rename to src/exchange/priceProvider/atomex/atomexPriceProvider.ts index d310f34a..605371e3 100644 --- a/src/exchange/ratesService/atomex/atomexRatesService.ts +++ b/src/exchange/priceProvider/atomex/atomexPriceProvider.ts @@ -3,9 +3,9 @@ import type BigNumber from 'bignumber.js'; import type { Currency } from '../../../common/index'; import type { ExchangeService } from '../../exchangeService'; import type { Quote } from '../../models/index'; -import type { RatesService } from '../ratesService'; +import type { PriceProvider } from '../priceProvider'; -export class AtomexRatesService implements RatesService { +export class AtomexPriceProvider implements PriceProvider { constructor( private readonly exchangeService: ExchangeService ) { } diff --git a/src/exchange/priceProvider/atomex/index.ts b/src/exchange/priceProvider/atomex/index.ts new file mode 100644 index 00000000..dffdaf6d --- /dev/null +++ b/src/exchange/priceProvider/atomex/index.ts @@ -0,0 +1 @@ +export { AtomexPriceProvider } from './atomexPriceProvider'; diff --git a/src/exchange/ratesService/binance/binanceRatesService.ts b/src/exchange/priceProvider/binance/binancePriceProvider.ts similarity index 82% rename from src/exchange/ratesService/binance/binanceRatesService.ts rename to src/exchange/priceProvider/binance/binancePriceProvider.ts index 8de36e3b..a4c98e2d 100644 --- a/src/exchange/ratesService/binance/binanceRatesService.ts +++ b/src/exchange/priceProvider/binance/binancePriceProvider.ts @@ -2,11 +2,11 @@ import BigNumber from 'bignumber.js'; import type { Currency } from '../../../common'; import { HttpClient } from '../../../core'; -import type { RatesService } from '../ratesService'; +import type { PriceProvider } from '../priceProvider'; import type { BinanceErrorDto, BinanceRatesDto } from './dtos'; import { isErrorDto } from './utils'; -export class BinanceRatesService implements RatesService { +export class BinancePriceProvider implements PriceProvider { private static readonly baseUrl = 'https://www.binance.com'; private static readonly priceUrlPath = '/api/v3/ticker/price'; @@ -14,7 +14,7 @@ export class BinanceRatesService implements RatesService { private _allSymbols: Set | undefined; constructor() { - this.httpClient = new HttpClient(BinanceRatesService.baseUrl); + this.httpClient = new HttpClient(BinancePriceProvider.baseUrl); } async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise { @@ -23,7 +23,7 @@ export class BinanceRatesService implements RatesService { if (!allSymbols.has(symbol)) return undefined; - const urlPath = `${BinanceRatesService.priceUrlPath}?symbol=${symbol}`; + const urlPath = `${BinancePriceProvider.priceUrlPath}?symbol=${symbol}`; const responseDto = await this.httpClient.request({ urlPath }, false); return this.mapRatesDtoToPrice(responseDto); @@ -44,7 +44,7 @@ export class BinanceRatesService implements RatesService { } private async requestAllSymbols(): Promise { - const urlPath = BinanceRatesService.priceUrlPath; + const urlPath = BinancePriceProvider.priceUrlPath; const responseDto = await this.httpClient.request({ urlPath }, false); return responseDto.map(dto => dto.symbol); diff --git a/src/exchange/ratesService/binance/dtos.ts b/src/exchange/priceProvider/binance/dtos.ts similarity index 100% rename from src/exchange/ratesService/binance/dtos.ts rename to src/exchange/priceProvider/binance/dtos.ts diff --git a/src/exchange/priceProvider/binance/index.ts b/src/exchange/priceProvider/binance/index.ts new file mode 100644 index 00000000..431d1276 --- /dev/null +++ b/src/exchange/priceProvider/binance/index.ts @@ -0,0 +1 @@ +export { BinancePriceProvider } from './binancePriceProvider'; diff --git a/src/exchange/ratesService/binance/utils.ts b/src/exchange/priceProvider/binance/utils.ts similarity index 100% rename from src/exchange/ratesService/binance/utils.ts rename to src/exchange/priceProvider/binance/utils.ts diff --git a/src/exchange/priceProvider/index.ts b/src/exchange/priceProvider/index.ts new file mode 100644 index 00000000..c122b62d --- /dev/null +++ b/src/exchange/priceProvider/index.ts @@ -0,0 +1,4 @@ +export type { PriceProvider } from './priceProvider'; +export { AtomexPriceProvider } from './atomex/index'; +export { BinancePriceProvider } from './binance/index'; +export { KrakenPriceProvider } from './kraken/index'; diff --git a/src/exchange/ratesService/kraken/dtos.ts b/src/exchange/priceProvider/kraken/dtos.ts similarity index 100% rename from src/exchange/ratesService/kraken/dtos.ts rename to src/exchange/priceProvider/kraken/dtos.ts diff --git a/src/exchange/priceProvider/kraken/index.ts b/src/exchange/priceProvider/kraken/index.ts new file mode 100644 index 00000000..34e763b5 --- /dev/null +++ b/src/exchange/priceProvider/kraken/index.ts @@ -0,0 +1 @@ +export { KrakenPriceProvider } from './krakenPriceProvider'; diff --git a/src/exchange/ratesService/kraken/krakenRatesService.ts b/src/exchange/priceProvider/kraken/krakenPriceProvider.ts similarity index 84% rename from src/exchange/ratesService/kraken/krakenRatesService.ts rename to src/exchange/priceProvider/kraken/krakenPriceProvider.ts index f0f2c3eb..80c7ca8b 100644 --- a/src/exchange/ratesService/kraken/krakenRatesService.ts +++ b/src/exchange/priceProvider/kraken/krakenPriceProvider.ts @@ -2,16 +2,16 @@ import BigNumber from 'bignumber.js'; import type { Currency } from '../../../common'; import { HttpClient } from '../../../core'; -import type { RatesService } from '../ratesService'; +import type { PriceProvider } from '../priceProvider'; import type { KrakenRatesDto } from './dtos'; -export class KrakenRatesService implements RatesService { +export class KrakenPriceProvider implements PriceProvider { private static readonly baseUrl = 'https://api.kraken.com'; private readonly httpClient: HttpClient; constructor() { - this.httpClient = new HttpClient(KrakenRatesService.baseUrl); + this.httpClient = new HttpClient(KrakenPriceProvider.baseUrl); } async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise { diff --git a/src/exchange/ratesService/ratesService.ts b/src/exchange/priceProvider/priceProvider.ts similarity index 85% rename from src/exchange/ratesService/ratesService.ts rename to src/exchange/priceProvider/priceProvider.ts index 943c13ec..e4eca514 100644 --- a/src/exchange/ratesService/ratesService.ts +++ b/src/exchange/priceProvider/priceProvider.ts @@ -2,6 +2,6 @@ import type BigNumber from 'bignumber.js'; import type { Currency } from '../../common'; -export interface RatesService { +export interface PriceProvider { getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise; } diff --git a/src/exchange/ratesService/atomex/index.ts b/src/exchange/ratesService/atomex/index.ts deleted file mode 100644 index 716f88b4..00000000 --- a/src/exchange/ratesService/atomex/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { AtomexRatesService } from './atomexRatesService'; diff --git a/src/exchange/ratesService/binance/index.ts b/src/exchange/ratesService/binance/index.ts deleted file mode 100644 index e91280f0..00000000 --- a/src/exchange/ratesService/binance/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { BinanceRatesService } from './binanceRatesService'; diff --git a/src/exchange/ratesService/index.ts b/src/exchange/ratesService/index.ts deleted file mode 100644 index ae192289..00000000 --- a/src/exchange/ratesService/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type { RatesService } from './ratesService'; -export { AtomexRatesService } from './atomex/index'; -export { BinanceRatesService } from './binance/index'; -export { KrakenRatesService } from './kraken/index'; diff --git a/src/exchange/ratesService/kraken/index.ts b/src/exchange/ratesService/kraken/index.ts deleted file mode 100644 index 9d3a4d52..00000000 --- a/src/exchange/ratesService/kraken/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { KrakenRatesService } from './krakenRatesService'; From 6015fc3c046e2d838cc7a59f977cd6fae9551dc3 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Wed, 24 Aug 2022 22:29:59 +0300 Subject: [PATCH 19/19] Refactor parameters --- src/atomex/atomex.ts | 2 +- src/common/disposable.ts | 3 +++ src/common/index.ts | 1 + src/exchange/priceManager/index.ts | 2 +- .../mixedPriceManager/mixedPriceManager.ts | 14 ++++++++----- src/exchange/priceManager/priceManager.ts | 21 +++++++++++++++---- 6 files changed, 32 insertions(+), 11 deletions(-) create mode 100644 src/common/disposable.ts diff --git a/src/atomex/atomex.ts b/src/atomex/atomex.ts index 79106c0b..03bf70b7 100644 --- a/src/atomex/atomex.ts +++ b/src/atomex/atomex.ts @@ -98,7 +98,7 @@ export class Atomex implements AtomexService { } async convertCurrency(fromAmount: BigNumber.Value, fromCurrency: Currency['id'], toCurrency: Currency['id']): Promise { - const price = await this.atomexContext.managers.priceManager.getAveragePrice(fromCurrency, toCurrency); + const price = await this.atomexContext.managers.priceManager.getAveragePrice({ baseCurrency: fromCurrency, quoteCurrency: toCurrency }); if (!price) return undefined; diff --git a/src/common/disposable.ts b/src/common/disposable.ts new file mode 100644 index 00000000..b15ea5c4 --- /dev/null +++ b/src/common/disposable.ts @@ -0,0 +1,3 @@ +export interface Disposable { + dispose(): Promise; +} diff --git a/src/common/index.ts b/src/common/index.ts index 67b3ddfe..5d466c6c 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -4,3 +4,4 @@ export { InMemoryCurrenciesProvider } from './inMemoryCurrenciesProvider'; export type { AtomexService } from './atomexService'; export type { CurrenciesProvider } from './currenciesProvider'; +export type { Disposable } from './disposable'; diff --git a/src/exchange/priceManager/index.ts b/src/exchange/priceManager/index.ts index b7af68c2..23379da8 100644 --- a/src/exchange/priceManager/index.ts +++ b/src/exchange/priceManager/index.ts @@ -1,2 +1,2 @@ -export type { PriceManager } from './priceManager'; +export type { PriceManager, GetPriceParameters, GetAveragePriceParameters } from './priceManager'; export { MixedPriceManager } from './mixedPriceManager/index'; diff --git a/src/exchange/priceManager/mixedPriceManager/mixedPriceManager.ts b/src/exchange/priceManager/mixedPriceManager/mixedPriceManager.ts index 1c3fb2a9..76958ba0 100644 --- a/src/exchange/priceManager/mixedPriceManager/mixedPriceManager.ts +++ b/src/exchange/priceManager/mixedPriceManager/mixedPriceManager.ts @@ -1,17 +1,17 @@ import BigNumber from 'bignumber.js'; -import type { Currency } from '../../../common'; +import { Currency, DataSource } from '../../../common'; import type { PriceProvider } from '../../priceProvider/index'; -import type { PriceManager } from '../priceManager'; +import type { GetAveragePriceParameters, GetPriceParameters, PriceManager } from '../priceManager'; export class MixedPriceManager implements PriceManager { constructor( private readonly providersMap: Map ) { } - async getAveragePrice(baseCurrency: string, quoteCurrency: string): Promise { + async getAveragePrice({ baseCurrency, quoteCurrency, dataSource = DataSource.All }: GetAveragePriceParameters): Promise { const providers = this.getAvailableProviders(); - const pricePromises = providers.map(provider => this.getPrice(baseCurrency, quoteCurrency, provider)); + const pricePromises = providers.map(provider => this.getPrice({ baseCurrency, quoteCurrency, provider })); const pricePromiseResults = await Promise.allSettled(pricePromises); const prices: BigNumber[] = []; @@ -22,7 +22,7 @@ export class MixedPriceManager implements PriceManager { return prices.length ? BigNumber.sum(...prices).div(prices.length) : undefined; } - async getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise { + async getPrice({ baseCurrency, quoteCurrency, provider, dataSource = DataSource.All }: GetPriceParameters): Promise { let price = await this.getPriceCore(baseCurrency, quoteCurrency, provider); if (!price) { const reversedPrice = await this.getPriceCore(quoteCurrency, baseCurrency, provider); @@ -37,6 +37,10 @@ export class MixedPriceManager implements PriceManager { return [...this.providersMap.keys()]; } + dispose(): Promise { + throw new Error('Method not implemented.'); + } + private async getPriceCore(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise { const providers = this.getSelectedProviders(provider); const pricePromises = providers.map(provider => provider.getPrice(baseCurrency, quoteCurrency)); diff --git a/src/exchange/priceManager/priceManager.ts b/src/exchange/priceManager/priceManager.ts index 5af2f3d5..013206b5 100644 --- a/src/exchange/priceManager/priceManager.ts +++ b/src/exchange/priceManager/priceManager.ts @@ -1,9 +1,22 @@ import type BigNumber from 'bignumber.js'; -import type { Currency } from '../../common'; +import type { Currency, DataSource, Disposable } from '../../common/index'; -export interface PriceManager { - getPrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id'], provider?: string): Promise; - getAveragePrice(baseCurrency: Currency['id'], quoteCurrency: Currency['id']): Promise; +export interface GetPriceParameters { + baseCurrency: Currency['id']; + quoteCurrency: Currency['id']; + provider?: string; + dataSource?: DataSource; +} + +export interface GetAveragePriceParameters { + baseCurrency: Currency['id']; + quoteCurrency: Currency['id']; + dataSource?: DataSource; +} + +export interface PriceManager extends Disposable { + getPrice(parameters: GetPriceParameters): Promise; + getAveragePrice(parameters: GetAveragePriceParameters): Promise; getAvailableProviders(): string[]; }