diff --git a/src/services/CoinGeckoPriceProvider.ts b/src/services/CoinGeckoPriceProvider.ts index be7ec66..e9ee539 100644 --- a/src/services/CoinGeckoPriceProvider.ts +++ b/src/services/CoinGeckoPriceProvider.ts @@ -1,8 +1,6 @@ -import axios, { AxiosRequestConfig } from 'axios'; -import { inject, injectable } from 'inversify'; +import axios from 'axios'; +import { injectable } from 'inversify'; import { IPriceProvider, TokenInfo } from './IPriceProvider'; -import { ContainerTypes } from '../containertypes'; -import { IFirebaseService } from './FirebaseService'; /** * Provides token price by using Coin Gecko API @@ -30,6 +28,26 @@ export class CoinGeckoPriceProvider implements IPriceProvider { return 0; } + public async getPrices(symbol: string, currencies = ['usd']): Promise> { + const tokenSymbol = await this.getTokenId(symbol); + const prices = new Map(); + currencies.map((c) => prices.set(c, 0)); + + if (tokenSymbol) { + const url = `${CoinGeckoPriceProvider.BaseUrl}/simple/price?ids=${tokenSymbol}&vs_currencies=${currencies}`; + const result = await axios.get(url); + + for (const [key, _] of prices) { + if (result.data[tokenSymbol]) { + const price = result.data[tokenSymbol][key]; + prices.set(key, Number(price ?? 0)); + } + } + } + + return prices; + } + public async getPriceWithTimestamp(symbol: string, currency: string | undefined): Promise { const price = await this.getPrice(symbol, currency); diff --git a/src/services/DiaDataPriceProvider.ts b/src/services/DiaDataPriceProvider.ts index a2c9256..26de7da 100644 --- a/src/services/DiaDataPriceProvider.ts +++ b/src/services/DiaDataPriceProvider.ts @@ -20,6 +20,10 @@ export class DiaDataPriceProvider implements IPriceProvider { return 0; } + public async getPrices(symbol: string, currencies: string[]): Promise> { + throw new Error('DIA Data API does not support multiple currencies in a single request.'); + } + public async getPriceWithTimestamp(symbol: string): Promise<{ price: number; lastUpdated: number }> { const price = await this.getPrice(symbol); diff --git a/src/services/IPriceProvider.ts b/src/services/IPriceProvider.ts index c1ff2f3..931a6f0 100644 --- a/src/services/IPriceProvider.ts +++ b/src/services/IPriceProvider.ts @@ -8,11 +8,18 @@ export type TokenInfo = { */ export interface IPriceProvider { /** - * Gets current token price in USD. + * Gets current token price in a given currency. * @param tokenInfo Token information. */ getPrice(symbol: string, currency: string | undefined): Promise; + /** + * Gets current token prices in a given list of currencies. + * @param symbol Token symbol. + * @param currencies + */ + getPrices(symbol: string, currencies: string[]): Promise>; + /** * Gets current token price in USD with timestamp. * @param tokenInfo Token price and timestamp. diff --git a/src/services/PriceProviderWithFailover.ts b/src/services/PriceProviderWithFailover.ts index b5b6b50..263da19 100644 --- a/src/services/PriceProviderWithFailover.ts +++ b/src/services/PriceProviderWithFailover.ts @@ -25,6 +25,10 @@ export class PriceProviderWithFailover implements IPriceProvider { return priceInfo.price; } + public async getPrices(symbol: string, currencies: string[]): Promise> { + throw new Error('getPrices method is not implemented in PriceProviderWithFailover.'); + } + public async getPriceWithTimestamp(symbol: string, currency = 'usd'): Promise { Guard.ThrowIfUndefined('symbol', symbol); diff --git a/src/services/StatsService.ts b/src/services/StatsService.ts index 3818e5c..2412ca3 100644 --- a/src/services/StatsService.ts +++ b/src/services/StatsService.ts @@ -45,7 +45,7 @@ const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); export class StatsService extends DappStakingV3IndexerBase implements IStatsService { constructor( @inject(ContainerTypes.ApiFactory) private _apiFactory: IApiFactory, - @inject(ContainerTypes.PriceProviderWithFailover) private _priceProvider: IPriceProvider, + @inject(ContainerTypes.PriceProvider) private _coinGeckoPriceProvider: IPriceProvider, ) { super(); } @@ -106,11 +106,11 @@ export class StatsService extends DappStakingV3IndexerBase implements IStatsServ ]); const prices: number[] = []; - for (const currency of currencies) { - const price = await this._priceProvider.getPrice(tokenSymbol.toLowerCase(), currency); - prices.push(price); - await delay(1000); // To avoid hitting the API rate limit - } + const result = await this._coinGeckoPriceProvider.getPrices(tokenSymbol.toLowerCase(), currencies); + currencies.map((currency) => { + const price = result.get(currency.toLowerCase()); + prices.push(price ?? 0); + }); const totalBalancesToExclude = this.getTotalBalanceToExclude(balancesToExclude); const circulatingSupplyWei = totalSupply.sub(totalBalancesToExclude);