diff --git a/CHANGELOG.md b/CHANGELOG.md index ae3f8d8f2..2c1d50d91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Refactored the API query parameters in various data provider services - Extended the _Storybook_ stories of the portfolio proportion chart component by a story using percentage values - Upgraded `@internationalized/number` from version `3.6.3` to `3.6.5` diff --git a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts index 4123cc6cc..d0d96acac 100644 --- a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts +++ b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts @@ -110,12 +110,14 @@ export class CoinGeckoService implements DataProviderInterface { [symbol: string]: { [date: string]: DataProviderHistoricalResponse }; }> { try { + const queryParams = new URLSearchParams({ + from: getUnixTime(from).toString(), + to: getUnixTime(to).toString(), + vs_currency: DEFAULT_CURRENCY.toLowerCase() + }); + const { error, prices, status } = await fetch( - `${ - this.apiUrl - }/coins/${symbol}/market_chart/range?vs_currency=${DEFAULT_CURRENCY.toLowerCase()}&from=${getUnixTime( - from - )}&to=${getUnixTime(to)}`, + `${this.apiUrl}/coins/${symbol}/market_chart/range?${queryParams.toString()}`, { headers: this.headers, signal: AbortSignal.timeout(requestTimeout) @@ -172,10 +174,13 @@ export class CoinGeckoService implements DataProviderInterface { } try { + const queryParams = new URLSearchParams({ + ids: symbols.join(','), + vs_currencies: DEFAULT_CURRENCY.toLowerCase() + }); + const quotes = await fetch( - `${this.apiUrl}/simple/price?ids=${symbols.join( - ',' - )}&vs_currencies=${DEFAULT_CURRENCY.toLowerCase()}`, + `${this.apiUrl}/simple/price?${queryParams.toString()}`, { headers: this.headers, signal: AbortSignal.timeout(requestTimeout) @@ -219,10 +224,17 @@ export class CoinGeckoService implements DataProviderInterface { let items: LookupItem[] = []; try { - const { coins } = await fetch(`${this.apiUrl}/search?query=${query}`, { - headers: this.headers, - signal: AbortSignal.timeout(requestTimeout) - }).then((res) => res.json()); + const queryParams = new URLSearchParams({ + query + }); + + const { coins } = await fetch( + `${this.apiUrl}/search?${queryParams.toString()}`, + { + headers: this.headers, + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => res.json()); items = coins.map(({ id: symbol, name }) => { return { diff --git a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts index b93ca492a..cd20fca44 100644 --- a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts +++ b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts @@ -96,17 +96,19 @@ export class EodHistoricalDataService implements DataProviderInterface { } try { + const queryParams = new URLSearchParams({ + api_token: this.apiKey, + fmt: 'json', + from: format(from, DATE_FORMAT), + to: format(to, DATE_FORMAT) + }); + const response: { [date: string]: DataProviderHistoricalResponse; } = {}; const historicalResult = await fetch( - `${this.URL}/div/${symbol}?api_token=${ - this.apiKey - }&fmt=json&from=${format(from, DATE_FORMAT)}&to=${format( - to, - DATE_FORMAT - )}`, + `${this.URL}/div/${symbol}?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -144,13 +146,16 @@ export class EodHistoricalDataService implements DataProviderInterface { symbol = this.convertToEodSymbol(symbol); try { + const queryParams = new URLSearchParams({ + api_token: this.apiKey, + fmt: 'json', + from: format(from, DATE_FORMAT), + period: granularity, + to: format(to, DATE_FORMAT) + }); + const response = await fetch( - `${this.URL}/eod/${symbol}?api_token=${ - this.apiKey - }&fmt=json&from=${format(from, DATE_FORMAT)}&to=${format( - to, - DATE_FORMAT - )}&period=${granularity}`, + `${this.URL}/eod/${symbol}?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -208,10 +213,14 @@ export class EodHistoricalDataService implements DataProviderInterface { }); try { + const queryParams = new URLSearchParams({ + api_token: this.apiKey, + fmt: 'json', + s: eodHistoricalDataSymbols.join(',') + }); + const realTimeResponse = await fetch( - `${this.URL}/real-time/${eodHistoricalDataSymbols[0]}?api_token=${ - this.apiKey - }&fmt=json&s=${eodHistoricalDataSymbols.join(',')}`, + `${this.URL}/real-time/${eodHistoricalDataSymbols[0]}?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -413,8 +422,12 @@ export class EodHistoricalDataService implements DataProviderInterface { })[] = []; try { + const queryParams = new URLSearchParams({ + api_token: this.apiKey + }); + const response = await fetch( - `${this.URL}/search/${query}?api_token=${this.apiKey}`, + `${this.URL}/search/${query}?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } diff --git a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts index fe8c4ecd6..27f462c90 100644 --- a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts +++ b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts @@ -85,8 +85,13 @@ export class FinancialModelingPrepService implements DataProviderInterface { symbol.length - DEFAULT_CURRENCY.length ); } else if (this.cryptocurrencyService.isCryptocurrency(symbol)) { + const queryParams = new URLSearchParams({ + symbol, + apikey: this.apiKey + }); + const [quote] = await fetch( - `${this.getUrl({ version: 'stable' })}/quote?symbol=${symbol}&apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/quote?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -99,8 +104,13 @@ export class FinancialModelingPrepService implements DataProviderInterface { ); response.name = quote.name; } else { + const queryParams = new URLSearchParams({ + symbol, + apikey: this.apiKey + }); + const [assetProfile] = await fetch( - `${this.getUrl({ version: 'stable' })}/profile?symbol=${symbol}&apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/profile?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -120,8 +130,13 @@ export class FinancialModelingPrepService implements DataProviderInterface { assetSubClass === AssetSubClass.ETF || assetSubClass === AssetSubClass.MUTUALFUND ) { + const queryParams = new URLSearchParams({ + symbol, + apikey: this.apiKey + }); + const etfCountryWeightings = await fetch( - `${this.getUrl({ version: 'stable' })}/etf/country-weightings?symbol=${symbol}&apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/etf/country-weightings?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -152,7 +167,7 @@ export class FinancialModelingPrepService implements DataProviderInterface { }); const etfHoldings = await fetch( - `${this.getUrl({ version: 'stable' })}/etf/holdings?symbol=${symbol}&apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/etf/holdings?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -171,7 +186,7 @@ export class FinancialModelingPrepService implements DataProviderInterface { ); const [etfInformation] = await fetch( - `${this.getUrl({ version: 'stable' })}/etf/info?symbol=${symbol}&apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/etf/info?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -182,7 +197,7 @@ export class FinancialModelingPrepService implements DataProviderInterface { } const etfSectorWeightings = await fetch( - `${this.getUrl({ version: 'stable' })}/etf/sector-weightings?symbol=${symbol}&apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/etf/sector-weightings?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -254,12 +269,17 @@ export class FinancialModelingPrepService implements DataProviderInterface { } try { + const queryParams = new URLSearchParams({ + symbol, + apikey: this.apiKey + }); + const response: { [date: string]: DataProviderHistoricalResponse; } = {}; const dividends = await fetch( - `${this.getUrl({ version: 'stable' })}/dividends?symbol=${symbol}&apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/dividends?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -319,8 +339,15 @@ export class FinancialModelingPrepService implements DataProviderInterface { ? addYears(currentFrom, MAX_YEARS_PER_REQUEST) : to; + const queryParams = new URLSearchParams({ + symbol, + apikey: this.apiKey, + from: format(currentFrom, DATE_FORMAT), + to: format(currentTo, DATE_FORMAT) + }); + const historical = await fetch( - `${this.getUrl({ version: 'stable' })}/historical-price-eod/full?symbol=${symbol}&apikey=${this.apiKey}&from=${format(currentFrom, DATE_FORMAT)}&to=${format(currentTo, DATE_FORMAT)}`, + `${this.getUrl({ version: 'stable' })}/historical-price-eod/full?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -375,6 +402,11 @@ export class FinancialModelingPrepService implements DataProviderInterface { [symbol: string]: Pick; } = {}; + const queryParams = new URLSearchParams({ + symbols: symbols.join(','), + apikey: this.apiKey + }); + const [assetProfileResolutions, quotes] = await Promise.all([ this.prismaService.assetProfileResolution.findMany({ where: { @@ -383,7 +415,7 @@ export class FinancialModelingPrepService implements DataProviderInterface { } }), fetch( - `${this.getUrl({ version: 'stable' })}/batch-quote-short?symbols=${symbols.join(',')}&apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/batch-quote-short?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -475,12 +507,18 @@ export class FinancialModelingPrepService implements DataProviderInterface { const assetProfileBySymbolMap: { [symbol: string]: Partial; } = {}; + let items: LookupItem[] = []; try { if (isISIN(query?.toUpperCase())) { + const queryParams = new URLSearchParams({ + apikey: this.apiKey, + isin: query.toUpperCase() + }); + const result = await fetch( - `${this.getUrl({ version: 'stable' })}/search-isin?isin=${query.toUpperCase()}&apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/search-isin?${queryParams.toString()}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -506,8 +544,13 @@ export class FinancialModelingPrepService implements DataProviderInterface { }; }); } else { + const queryParams = new URLSearchParams({ + query, + apikey: this.apiKey + }); + const result = await fetch( - `${this.getUrl({ version: 'stable' })}/search-symbol?query=${query}&apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/search-symbol?${queryParams.toString()}`, { signal: AbortSignal.timeout( this.configurationService.get('REQUEST_TIMEOUT') diff --git a/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts b/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts index afbecc118..2b49e89c2 100644 --- a/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts +++ b/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts @@ -116,11 +116,14 @@ export class GhostfolioService implements DataProviderInterface { } = {}; try { + const queryParams = new URLSearchParams({ + granularity, + from: format(from, DATE_FORMAT), + to: format(to, DATE_FORMAT) + }); + const response = await fetch( - `${this.URL}/v2/data-providers/ghostfolio/dividends/${symbol}?from=${format(from, DATE_FORMAT)}&granularity=${granularity}&to=${format( - to, - DATE_FORMAT - )}`, + `${this.URL}/v2/data-providers/ghostfolio/dividends/${symbol}?${queryParams.toString()}`, { headers: await this.getRequestHeaders(), signal: AbortSignal.timeout(requestTimeout) @@ -165,11 +168,14 @@ export class GhostfolioService implements DataProviderInterface { [symbol: string]: { [date: string]: DataProviderHistoricalResponse }; }> { try { + const queryParams = new URLSearchParams({ + granularity, + from: format(from, DATE_FORMAT), + to: format(to, DATE_FORMAT) + }); + const response = await fetch( - `${this.URL}/v2/data-providers/ghostfolio/historical/${symbol}?from=${format(from, DATE_FORMAT)}&granularity=${granularity}&to=${format( - to, - DATE_FORMAT - )}`, + `${this.URL}/v2/data-providers/ghostfolio/historical/${symbol}?${queryParams.toString()}`, { headers: await this.getRequestHeaders(), signal: AbortSignal.timeout(requestTimeout) @@ -235,8 +241,12 @@ export class GhostfolioService implements DataProviderInterface { } try { + const queryParams = new URLSearchParams({ + symbols: symbols.join(',') + }); + const response = await fetch( - `${this.URL}/v2/data-providers/ghostfolio/quotes?symbols=${symbols.join(',')}`, + `${this.URL}/v2/data-providers/ghostfolio/quotes?${queryParams.toString()}`, { headers: await this.getRequestHeaders(), signal: AbortSignal.timeout(requestTimeout) @@ -288,8 +298,12 @@ export class GhostfolioService implements DataProviderInterface { let searchResult: LookupResponse = { items: [] }; try { + const queryParams = new URLSearchParams({ + query + }); + const response = await fetch( - `${this.URL}/v2/data-providers/ghostfolio/lookup?query=${query}`, + `${this.URL}/v2/data-providers/ghostfolio/lookup?${queryParams.toString()}`, { headers: await this.getRequestHeaders(), signal: AbortSignal.timeout(requestTimeout)