Browse Source

fix: @typescript-eslint/consistent-indexed-object-style

Signed-off-by: Dominik Willner <th33xitus@gmail.com>
pull/3986/head
dw-0 10 months ago
parent
commit
271c6d2c40
  1. 3
      .eslintrc.json
  2. 1
      CHANGELOG.md
  3. 5
      apps/api/src/app/account-balance/account-balance.service.ts
  4. 4
      apps/api/src/app/admin/update-asset-profile.dto.ts
  5. 6
      apps/api/src/app/import/import.service.ts
  6. 6
      apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts
  7. 89
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  8. 52
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts
  9. 6
      apps/api/src/app/portfolio/portfolio.service.ts
  10. 9
      apps/api/src/app/symbol/symbol.service.ts
  11. 2
      apps/api/src/helper/object.helper.ts
  12. 2
      apps/api/src/middlewares/html-template.middleware.ts
  13. 4
      apps/api/src/models/interfaces/portfolio.interface.ts
  14. 9
      apps/api/src/models/rules/account-cluster-risk/current-investment.ts
  15. 30
      apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts
  16. 44
      apps/api/src/services/data-provider/coingecko/coingecko.service.ts
  17. 85
      apps/api/src/services/data-provider/data-provider.service.ts
  18. 49
      apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts
  19. 44
      apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts
  20. 46
      apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts
  21. 30
      apps/api/src/services/data-provider/interfaces/data-provider.interface.ts
  22. 48
      apps/api/src/services/data-provider/manual/manual.service.ts
  23. 35
      apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts
  24. 50
      apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts
  25. 29
      apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts
  26. 2
      apps/api/src/services/i18n/i18n.service.ts
  27. 4
      apps/api/src/services/property/property.service.ts
  28. 2
      apps/api/src/services/queues/data-gathering/data-gathering.service.ts
  29. 6
      apps/api/src/services/symbol-profile/symbol-profile.service.ts
  30. 11
      apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.ts
  31. 8
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
  32. 8
      apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
  33. 2
      apps/client/src/app/components/world-map-chart/world-map-chart.component.ts
  34. 4
      apps/client/src/app/pages/landing/landing-page.component.ts
  35. 63
      apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
  36. 31
      apps/client/src/app/pages/public/public-page.component.ts
  37. 8
      libs/common/src/lib/class-transformer.ts
  38. 2
      libs/common/src/lib/interfaces/admin-data.interface.ts
  39. 2
      libs/common/src/lib/interfaces/enhanced-symbol-profile.interface.ts
  40. 20
      libs/common/src/lib/interfaces/portfolio-details.interface.ts
  41. 2
      libs/common/src/lib/interfaces/portfolio-item.interface.ts
  42. 2
      libs/common/src/lib/interfaces/portfolio-report.interface.ts
  43. 9
      libs/common/src/lib/interfaces/responses/public-portfolio-response.interface.ts
  44. 2
      libs/common/src/lib/interfaces/scraper-configuration.interface.ts
  45. 38
      libs/common/src/lib/interfaces/symbol-metrics.interface.ts
  46. 4
      libs/common/src/lib/models/timeline-position.ts
  47. 2
      libs/ui/src/lib/assistant/assistant.component.ts
  48. 24
      libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts

3
.eslintrc.json

@ -142,8 +142,7 @@
// The following rules are part of @typescript-eslint/stylistic-type-checked
// and can be remove once solved
"@typescript-eslint/prefer-nullish-coalescing": "warn", // TODO: Requires strictNullChecks: true
"@typescript-eslint/consistent-indexed-object-style": "warn"
"@typescript-eslint/prefer-nullish-coalescing": "warn" // TODO: Requires strictNullChecks: true
}
}
],

1
CHANGELOG.md

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Switched the `consistent-type-assertions` rule from `warn` to `error` in the `eslint` configuration
- Switched the `prefer-optional-chain` rule from `warn` to `error` in the `eslint` configuration
- Switched the `consistent-generic-constructors` rule from `warn` to `error` in the `eslint` configuration
- Switched the `consistent-indexed-object-style` rule from `warn` to `error` in the `eslint` configuration
### Fixed

5
apps/api/src/app/account-balance/account-balance.service.ts

@ -110,9 +110,8 @@ export class AccountBalanceService {
userId,
withExcludedAccounts: false // TODO
});
const accumulatedBalancesByDate: { [date: string]: HistoricalDataItem } =
{};
const lastBalancesByAccount: { [accountId: string]: Big } = {};
const accumulatedBalancesByDate: Record<string, HistoricalDataItem> = {};
const lastBalancesByAccount: Record<string, Big> = {};
for (const { accountId, date, valueInBaseCurrency } of balances) {
const formattedDate = format(date, DATE_FORMAT);

4
apps/api/src/app/admin/update-asset-profile.dto.ts

@ -45,9 +45,7 @@ export class UpdateAssetProfileDto {
@IsObject()
@IsOptional()
symbolMapping?: {
[dataProvider: string]: string;
};
symbolMapping?: Record<string, string>;
@IsOptional()
@IsUrl({

6
apps/api/src/app/import/import.service.ts

@ -158,7 +158,7 @@ export class ImportService {
maxActivitiesToImport: number;
user: UserWithSettings;
}): Promise<Activity[]> {
const accountIdMapping: { [oldAccountId: string]: string } = {};
const accountIdMapping: Record<string, string> = {};
const userCurrency = user.Settings.settings.baseCurrency;
if (!isDryRun && accountsDto?.length) {
@ -579,9 +579,7 @@ export class ImportService {
throw new Error(`Too many activities (${maxActivitiesToImport} at most)`);
}
const assetProfiles: {
[assetProfileIdentifier: string]: Partial<SymbolProfile>;
} = {};
const assetProfiles: Record<string, Partial<SymbolProfile>> = {};
for (const [
index,

6
apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts

@ -12,10 +12,8 @@ export class MWRPortfolioCalculator extends PortfolioCalculator {
protected getSymbolMetrics({}: {
end: Date;
exchangeRates: { [dateString: string]: number };
marketSymbolMap: {
[date: string]: { [symbol: string]: Big };
};
exchangeRates: Record<string, number>;
marketSymbolMap: Record<string, Record<string, Big>>;
start: Date;
step?: number;
} & AssetProfileIdentifier): SymbolMetrics {

89
apps/api/src/app/portfolio/calculator/portfolio-calculator.ts

@ -1,16 +1,3 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { PortfolioOrder } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-order.interface';
import { PortfolioSnapshotValue } from '@ghostfolio/api/app/portfolio/interfaces/snapshot-value.interface';
import { TransactionPointSymbol } from '@ghostfolio/api/app/portfolio/interfaces/transaction-point-symbol.interface';
import { TransactionPoint } from '@ghostfolio/api/app/portfolio/interfaces/transaction-point.interface';
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
import { getFactor } from '@ghostfolio/api/helper/portfolio.helper';
import { LogPerformance } from '@ghostfolio/api/interceptors/performance-logging/performance-logging.interceptor';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces';
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper';
import {
PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME,
@ -51,6 +38,20 @@ import {
} from 'date-fns';
import { first, isNumber, last, sortBy, sum, uniq, uniqBy } from 'lodash';
import { getFactor } from '../../../helper/portfolio.helper';
import { LogPerformance } from '../../../interceptors/performance-logging/performance-logging.interceptor';
import { ConfigurationService } from '../../../services/configuration/configuration.service';
import { ExchangeRateDataService } from '../../../services/exchange-rate-data/exchange-rate-data.service';
import { IDataGatheringItem } from '../../../services/interfaces/interfaces';
import { PortfolioSnapshotService } from '../../../services/queues/portfolio-snapshot/portfolio-snapshot.service';
import { Activity } from '../../order/interfaces/activities.interface';
import { RedisCacheService } from '../../redis-cache/redis-cache.service';
import { CurrentRateService } from '../current-rate.service';
import { PortfolioOrder } from '../interfaces/portfolio-order.interface';
import { PortfolioSnapshotValue } from '../interfaces/snapshot-value.interface';
import { TransactionPointSymbol } from '../interfaces/transaction-point-symbol.interface';
import { TransactionPoint } from '../interfaces/transaction-point.interface';
export abstract class PortfolioCalculator {
protected static readonly ENABLE_LOGGING = false;
@ -188,7 +189,7 @@ export abstract class PortfolioCalculator {
};
}
const currencies: { [symbol: string]: string } = {};
const currencies: Record<string, string> = {};
const dataGatheringItems: IDataGatheringItem[] = [];
let firstIndex = transactionPoints.length;
let firstTransactionPoint: TransactionPoint = null;
@ -239,9 +240,7 @@ export abstract class PortfolioCalculator {
this.dataProviderInfos = dataProviderInfos;
const marketSymbolMap: {
[date: string]: { [symbol: string]: Big };
} = {};
const marketSymbolMap: Record<string, Record<string, Big>> = {};
for (const marketSymbol of marketSymbols) {
const date = format(marketSymbol.date, DATE_FORMAT);
@ -290,8 +289,9 @@ export abstract class PortfolioCalculator {
const errors: ResponseError['errors'] = [];
const accumulatedValuesByDate: {
[date: string]: {
const accumulatedValuesByDate: Record<
string,
{
investmentValueWithCurrencyEffect: Big;
totalAccountBalanceWithCurrencyEffect: Big;
totalCurrentValue: Big;
@ -302,22 +302,23 @@ export abstract class PortfolioCalculator {
totalNetPerformanceValueWithCurrencyEffect: Big;
totalTimeWeightedInvestmentValue: Big;
totalTimeWeightedInvestmentValueWithCurrencyEffect: Big;
};
} = {};
const valuesBySymbol: {
[symbol: string]: {
currentValues: { [date: string]: Big };
currentValuesWithCurrencyEffect: { [date: string]: Big };
investmentValuesAccumulated: { [date: string]: Big };
investmentValuesAccumulatedWithCurrencyEffect: { [date: string]: Big };
investmentValuesWithCurrencyEffect: { [date: string]: Big };
netPerformanceValues: { [date: string]: Big };
netPerformanceValuesWithCurrencyEffect: { [date: string]: Big };
timeWeightedInvestmentValues: { [date: string]: Big };
timeWeightedInvestmentValuesWithCurrencyEffect: { [date: string]: Big };
};
} = {};
}
> = {};
const valuesBySymbol: Record<
string,
{
currentValues: Record<string, Big>;
currentValuesWithCurrencyEffect: Record<string, Big>;
investmentValuesAccumulated: Record<string, Big>;
investmentValuesAccumulatedWithCurrencyEffect: Record<string, Big>;
investmentValuesWithCurrencyEffect: Record<string, Big>;
netPerformanceValues: Record<string, Big>;
netPerformanceValuesWithCurrencyEffect: Record<string, Big>;
timeWeightedInvestmentValues: Record<string, Big>;
timeWeightedInvestmentValuesWithCurrencyEffect: Record<string, Big>;
}
> = {};
for (const item of lastTransactionPoint.items) {
const feeInBaseCurrency = item.fee.mul(
@ -461,10 +462,10 @@ export abstract class PortfolioCalculator {
return map;
},
{} as { [date: string]: Big }
{} as Record<string, Big>
);
const accountBalanceMap: { [date: string]: Big } = {};
const accountBalanceMap: Record<string, Big> = {};
let lastKnownBalance = new Big(0);
@ -670,7 +671,7 @@ export abstract class PortfolioCalculator {
data: HistoricalDataItem[];
groupBy: GroupBy;
}): InvestmentItem[] {
const groupedData: { [dateGroup: string]: Big } = {};
const groupedData: Record<string, Big> = {};
for (const { date, investmentValueWithCurrencyEffect } of data) {
const dateGroup =
@ -802,12 +803,10 @@ export abstract class PortfolioCalculator {
start,
symbol
}: {
chartDateMap: { [date: string]: boolean };
chartDateMap: Record<string, boolean>;
end: Date;
exchangeRates: { [dateString: string]: number };
marketSymbolMap: {
[date: string]: { [symbol: string]: Big };
};
exchangeRates: Record<string, number>;
marketSymbolMap: Record<string, Record<string, Big>>;
start: Date;
} & AssetProfileIdentifier): SymbolMetrics;
@ -829,7 +828,7 @@ export abstract class PortfolioCalculator {
endDate: Date;
startDate: Date;
step: number;
}): { [date: string]: true } {
}): Record<string, true> {
// Create a map of all relevant chart dates:
// 1. Add transaction point dates
const chartDateMap = this.transactionPoints.reduce((result, { date }) => {
@ -892,7 +891,7 @@ export abstract class PortfolioCalculator {
@LogPerformance
private computeTransactionPoints() {
this.transactionPoints = [];
const symbols: { [symbol: string]: TransactionPointSymbol } = {};
const symbols: Record<string, TransactionPointSymbol> = {};
let lastDate: string = null;
let lastTransactionPoint: TransactionPoint = null;

52
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts

@ -1,6 +1,3 @@
import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator';
import { PortfolioOrderItem } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-order-item.interface';
import { getFactor } from '@ghostfolio/api/helper/portfolio.helper';
import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper';
import { DATE_FORMAT } from '@ghostfolio/common/helper';
import {
@ -15,6 +12,10 @@ import { Big } from 'big.js';
import { addMilliseconds, differenceInDays, format, isBefore } from 'date-fns';
import { cloneDeep, first, last, sortBy } from 'lodash';
import { getFactor } from '../../../../helper/portfolio.helper';
import { PortfolioOrderItem } from '../../interfaces/portfolio-order-item.interface';
import { PortfolioCalculator } from '../portfolio-calculator';
export class TWRPortfolioCalculator extends PortfolioCalculator {
private chartDates: string[];
@ -116,17 +117,15 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
start,
symbol
}: {
chartDateMap?: { [date: string]: boolean };
chartDateMap?: Record<string, boolean>;
end: Date;
exchangeRates: { [dateString: string]: number };
marketSymbolMap: {
[date: string]: { [symbol: string]: Big };
};
exchangeRates: Record<string, number>;
marketSymbolMap: Record<string, Record<string, Big>>;
start: Date;
} & AssetProfileIdentifier): SymbolMetrics {
const currentExchangeRate = exchangeRates[format(new Date(), DATE_FORMAT)];
const currentValues: { [date: string]: Big } = {};
const currentValuesWithCurrencyEffect: { [date: string]: Big } = {};
const currentValues: Record<string, Big> = {};
const currentValuesWithCurrencyEffect: Record<string, Big> = {};
let fees = new Big(0);
let feesAtStartDate = new Big(0);
let feesAtStartDateWithCurrencyEffect = new Big(0);
@ -141,20 +140,18 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
let initialValueWithCurrencyEffect: Big;
let investmentAtStartDate: Big;
let investmentAtStartDateWithCurrencyEffect: Big;
const investmentValuesAccumulated: { [date: string]: Big } = {};
const investmentValuesAccumulatedWithCurrencyEffect: {
[date: string]: Big;
} = {};
const investmentValuesWithCurrencyEffect: { [date: string]: Big } = {};
const investmentValuesAccumulated: Record<string, Big> = {};
const investmentValuesAccumulatedWithCurrencyEffect: Record<string, Big> =
{};
const investmentValuesWithCurrencyEffect: Record<string, Big> = {};
let lastAveragePrice = new Big(0);
let lastAveragePriceWithCurrencyEffect = new Big(0);
const netPerformanceValues: { [date: string]: Big } = {};
const netPerformanceValuesWithCurrencyEffect: { [date: string]: Big } = {};
const timeWeightedInvestmentValues: { [date: string]: Big } = {};
const netPerformanceValues: Record<string, Big> = {};
const netPerformanceValuesWithCurrencyEffect: Record<string, Big> = {};
const timeWeightedInvestmentValues: Record<string, Big> = {};
const timeWeightedInvestmentValuesWithCurrencyEffect: {
[date: string]: Big;
} = {};
const timeWeightedInvestmentValuesWithCurrencyEffect: Record<string, Big> =
{};
const totalAccountBalanceInBaseCurrency = new Big(0);
let totalDividend = new Big(0);
@ -301,7 +298,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
let lastUnitPrice: Big;
const ordersByDate: { [date: string]: PortfolioOrderItem[] } = {};
const ordersByDate: Record<string, PortfolioOrderItem[]> = {};
for (const order of orders) {
ordersByDate[order.date] = ordersByDate[order.date] ?? [];
@ -788,13 +785,12 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
)
: new Big(0);
const netPerformancePercentageWithCurrencyEffectMap: {
[key: DateRange]: Big;
} = {};
const netPerformancePercentageWithCurrencyEffectMap: Record<
DateRange,
Big
> = {};
const netPerformanceWithCurrencyEffectMap: {
[key: DateRange]: Big;
} = {};
const netPerformanceWithCurrencyEffectMap: Record<DateRange, Big> = {};
for (const dateRange of [
'1d',

6
apps/api/src/app/portfolio/portfolio.service.ts

@ -423,12 +423,12 @@ export class PortfolioService {
const symbolProfiles =
await this.symbolProfileService.getSymbolProfiles(dataGatheringItems);
const symbolProfileMap: { [symbol: string]: EnhancedSymbolProfile } = {};
const symbolProfileMap: Record<string, EnhancedSymbolProfile> = {};
for (const symbolProfile of symbolProfiles) {
symbolProfileMap[symbolProfile.symbol] = symbolProfile;
}
const portfolioItemsNow: { [symbol: string]: TimelinePosition } = {};
const portfolioItemsNow: Record<string, TimelinePosition> = {};
for (const position of positions) {
portfolioItemsNow[position.symbol] = position;
}
@ -969,7 +969,7 @@ export class PortfolioService {
)
]);
const symbolProfileMap: { [symbol: string]: EnhancedSymbolProfile } = {};
const symbolProfileMap: Record<string, EnhancedSymbolProfile> = {};
for (const symbolProfile of symbolProfiles) {
symbolProfileMap[symbolProfile.symbol] = symbolProfile;

9
apps/api/src/app/symbol/symbol.service.ts

@ -74,11 +74,10 @@ export class SymbolService {
date = new Date(),
symbol
}: IDataGatheringItem): Promise<IDataProviderHistoricalResponse> {
let historicalData: {
[symbol: string]: {
[date: string]: IDataProviderHistoricalResponse;
};
} = {
let historicalData: Record<
string,
Record<string, IDataProviderHistoricalResponse>
> = {
[symbol]: {}
};

2
apps/api/src/helper/object.helper.ts

@ -38,7 +38,7 @@ export function redactAttributes({
}: {
isFirstRun?: boolean;
object: any;
options: { attribute: string; valueMap: { [key: string]: any } }[];
options: { attribute: string; valueMap: Record<string, any> }[];
}): any {
if (!object || !options?.length) {
return object;

2
apps/api/src/middlewares/html-template.middleware.ts

@ -14,7 +14,7 @@ import { join } from 'path';
const i18nService = new I18nService();
let indexHtmlMap: { [languageCode: string]: string } = {};
let indexHtmlMap: Record<string, string> = {};
const title = 'Ghostfolio';

4
apps/api/src/models/interfaces/portfolio.interface.ts

@ -7,9 +7,7 @@ export interface PortfolioInterface {
getFees(): number;
getPositions(aDate: Date): {
[symbol: string]: Position;
};
getPositions(aDate: Date): Record<string, Position>;
getSymbols(aDate?: Date): string[];

9
apps/api/src/models/rules/account-cluster-risk/current-investment.ts

@ -23,11 +23,12 @@ export class AccountClusterRiskCurrentInvestment extends Rule<Settings> {
}
public evaluate(ruleSettings: Settings) {
const accounts: {
[symbol: string]: Pick<PortfolioPosition, 'name'> & {
const accounts: Record<
string,
Pick<PortfolioPosition, 'name'> & {
investment: number;
};
} = {};
}
> = {};
for (const [accountId, account] of Object.entries(this.accounts)) {
accounts[accountId] = {

30
apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts

@ -64,20 +64,20 @@ export class AlphaVantageService implements DataProviderInterface {
from,
symbol,
to
}: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}> {
}: GetHistoricalParams): Promise<
Record<string, Record<string, IDataProviderHistoricalResponse>>
> {
try {
const historicalData: {
[symbol: string]: IAlphaVantageHistoricalResponse[];
} = await this.alphaVantage.crypto.daily(
symbol.substring(0, symbol.length - 3).toLowerCase(),
'usd'
);
const historicalData: Record<string, IAlphaVantageHistoricalResponse[]> =
await this.alphaVantage.crypto.daily(
symbol.substring(0, symbol.length - 3).toLowerCase(),
'usd'
);
const response: {
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
} = {};
const response: Record<
string,
Record<string, IDataProviderHistoricalResponse>
> = {};
response[symbol] = {};
@ -109,9 +109,9 @@ export class AlphaVantageService implements DataProviderInterface {
return DataSource.ALPHA_VANTAGE;
}
public async getQuotes({}: GetQuotesParams): Promise<{
[symbol: string]: IDataProviderResponse;
}> {
public async getQuotes({}: GetQuotesParams): Promise<
Record<string, IDataProviderResponse>
> {
return {};
}

44
apps/api/src/services/data-provider/coingecko/coingecko.service.ts

@ -1,16 +1,3 @@
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '@ghostfolio/api/services/data-provider/interfaces/data-provider.interface';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '@ghostfolio/api/services/interfaces/interfaces';
import { DEFAULT_CURRENCY } from '@ghostfolio/common/config';
import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { DataProviderInfo } from '@ghostfolio/common/interfaces';
@ -25,6 +12,20 @@ import {
import { format, fromUnixTime, getUnixTime } from 'date-fns';
import got, { Headers } from 'got';
import { LookupItem } from '../../../app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '../../configuration/configuration.service';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '../../interfaces/interfaces';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '../interfaces/data-provider.interface';
@Injectable()
export class CoinGeckoService implements DataProviderInterface {
private readonly apiUrl: string;
@ -111,9 +112,9 @@ export class CoinGeckoService implements DataProviderInterface {
requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'),
symbol,
to
}: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}> {
}: GetHistoricalParams): Promise<
Record<string, Record<string, IDataProviderHistoricalResponse>>
> {
try {
const abortController = new AbortController();
@ -134,9 +135,10 @@ export class CoinGeckoService implements DataProviderInterface {
}
).json<any>();
const result: {
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
} = {
const result: Record<
string,
Record<string, IDataProviderHistoricalResponse>
> = {
[symbol]: {}
};
@ -168,8 +170,8 @@ export class CoinGeckoService implements DataProviderInterface {
public async getQuotes({
requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'),
symbols
}: GetQuotesParams): Promise<{ [symbol: string]: IDataProviderResponse }> {
const response: { [symbol: string]: IDataProviderResponse } = {};
}: GetQuotesParams): Promise<Record<string, IDataProviderResponse>> {
const response: Record<string, IDataProviderResponse> = {};
if (symbols.length <= 0) {
return response;

85
apps/api/src/services/data-provider/data-provider.service.ts

@ -1,14 +1,3 @@
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { DataProviderInterface } from '@ghostfolio/api/services/data-provider/interfaces/data-provider.interface';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '@ghostfolio/api/services/interfaces/interfaces';
import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service';
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { PropertyService } from '@ghostfolio/api/services/property/property.service';
import {
DEFAULT_CURRENCY,
DERIVED_CURRENCIES,
@ -30,9 +19,21 @@ import { eachDayOfInterval, format, isValid } from 'date-fns';
import { groupBy, isEmpty, isNumber, uniqWith } from 'lodash';
import ms from 'ms';
import { RedisCacheService } from '../../app/redis-cache/redis-cache.service';
import { LookupItem } from '../../app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '../configuration/configuration.service';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '../interfaces/interfaces';
import { MarketDataService } from '../market-data/market-data.service';
import { PrismaService } from '../prisma/prisma.service';
import { PropertyService } from '../property/property.service';
import { DataProviderInterface } from './interfaces/data-provider.interface';
@Injectable()
export class DataProviderService {
private dataProviderMapping: { [dataProviderName: string]: string };
private dataProviderMapping: Record<string, string>;
public constructor(
private readonly configurationService: ConfigurationService,
@ -48,9 +49,9 @@ export class DataProviderService {
public async initialize() {
this.dataProviderMapping =
((await this.propertyService.getByKey(PROPERTY_DATA_SOURCE_MAPPING)) as {
[dataProviderName: string]: string;
}) ?? {};
((await this.propertyService.getByKey(
PROPERTY_DATA_SOURCE_MAPPING
)) as Record<string, string>) ?? {};
}
public async checkQuote(dataSource: DataSource) {
@ -75,12 +76,10 @@ export class DataProviderService {
return false;
}
public async getAssetProfiles(items: AssetProfileIdentifier[]): Promise<{
[symbol: string]: Partial<SymbolProfile>;
}> {
const response: {
[symbol: string]: Partial<SymbolProfile>;
} = {};
public async getAssetProfiles(
items: AssetProfileIdentifier[]
): Promise<Record<string, Partial<SymbolProfile>>> {
const response: Record<string, Partial<SymbolProfile>> = {};
const itemsGroupedByDataSource = groupBy(items, ({ dataSource }) => {
return dataSource;
@ -177,12 +176,11 @@ export class DataProviderService {
aGranularity: Granularity = 'month',
from: Date,
to: Date
): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}> {
let response: {
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
} = {};
): Promise<Record<string, Record<string, IDataProviderHistoricalResponse>>> {
let response: Record<
string,
Record<string, IDataProviderHistoricalResponse>
> = {};
if (isEmpty(aItems) || !isValid(from) || !isValid(to)) {
return response;
@ -246,9 +244,7 @@ export class DataProviderService {
dataGatheringItems: AssetProfileIdentifier[];
from: Date;
to: Date;
}): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}> {
}): Promise<Record<string, Record<string, IDataProviderHistoricalResponse>>> {
for (const { currency, rootCurrency } of DERIVED_CURRENCIES) {
if (
this.hasCurrency({
@ -272,21 +268,20 @@ export class DataProviderService {
return obj1.dataSource === obj2.dataSource && obj1.symbol === obj2.symbol;
});
const result: {
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
} = {};
const result: Record<
string,
Record<string, IDataProviderHistoricalResponse>
> = {};
const promises: Promise<{
data: { [date: string]: IDataProviderHistoricalResponse };
data: Record<string, IDataProviderHistoricalResponse>;
symbol: string;
}>[] = [];
for (const { dataSource, symbol } of dataGatheringItems) {
const dataProvider = this.getDataProvider(dataSource);
if (dataProvider.canHandle(symbol)) {
if (symbol === `${DEFAULT_CURRENCY}USX`) {
const data: {
[date: string]: IDataProviderHistoricalResponse;
} = {};
const data: Record<string, IDataProviderHistoricalResponse> = {};
for (const date of eachDayOfInterval({ end: to, start: from })) {
data[format(date, DATE_FORMAT)] = { marketPrice: 100 };
@ -354,12 +349,8 @@ export class DataProviderService {
requestTimeout?: number;
useCache?: boolean;
user?: UserWithSettings;
}): Promise<{
[symbol: string]: IDataProviderResponse;
}> {
const response: {
[symbol: string]: IDataProviderResponse;
} = {};
}): Promise<Record<string, IDataProviderResponse>> {
const response: Record<string, IDataProviderResponse> = {};
const startTimeTotal = performance.now();
if (
@ -651,9 +642,7 @@ export class DataProviderService {
factor
}: {
allData: {
data: {
[date: string]: IDataProviderHistoricalResponse;
};
data: Record<string, IDataProviderHistoricalResponse>;
symbol: string;
}[];
currency: string;
@ -663,9 +652,7 @@ export class DataProviderService {
return symbol === currency;
})?.data;
const data: {
[date: string]: IDataProviderHistoricalResponse;
} = {};
const data: Record<string, IDataProviderHistoricalResponse> = {};
for (const date in rootData) {
if (isNumber(rootData[date].marketPrice)) {

49
apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts

@ -1,17 +1,3 @@
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '@ghostfolio/api/services/data-provider/interfaces/data-provider.interface';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '@ghostfolio/api/services/interfaces/interfaces';
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service';
import {
DEFAULT_CURRENCY,
REPLACE_NAME_PARTS
@ -31,6 +17,21 @@ import { addDays, format, isSameDay, isToday } from 'date-fns';
import got from 'got';
import { isNumber } from 'lodash';
import { LookupItem } from '../../../app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '../../configuration/configuration.service';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '../../interfaces/interfaces';
import { SymbolProfileService } from '../../symbol-profile/symbol-profile.service';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '../interfaces/data-provider.interface';
@Injectable()
export class EodHistoricalDataService implements DataProviderInterface {
private apiKey: string;
@ -78,9 +79,9 @@ export class EodHistoricalDataService implements DataProviderInterface {
requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'),
symbol,
to
}: GetDividendsParams): Promise<{
[date: string]: IDataProviderHistoricalResponse;
}> {
}: GetDividendsParams): Promise<
Record<string, IDataProviderHistoricalResponse>
> {
symbol = this.convertToEodSymbol(symbol);
if (isSameDay(from, to)) {
@ -90,9 +91,7 @@ export class EodHistoricalDataService implements DataProviderInterface {
try {
const abortController = new AbortController();
const response: {
[date: string]: IDataProviderHistoricalResponse;
} = {};
const response: Record<string, IDataProviderHistoricalResponse> = {};
setTimeout(() => {
abortController.abort();
@ -137,9 +136,9 @@ export class EodHistoricalDataService implements DataProviderInterface {
requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'),
symbol,
to
}: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}> {
}: GetHistoricalParams): Promise<
Record<string, Record<string, IDataProviderHistoricalResponse>>
> {
symbol = this.convertToEodSymbol(symbol);
try {
@ -202,8 +201,8 @@ export class EodHistoricalDataService implements DataProviderInterface {
public async getQuotes({
requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'),
symbols
}: GetQuotesParams): Promise<{ [symbol: string]: IDataProviderResponse }> {
const response: { [symbol: string]: IDataProviderResponse } = {};
}: GetQuotesParams): Promise<Record<string, IDataProviderResponse>> {
const response: Record<string, IDataProviderResponse> = {};
if (symbols.length <= 0) {
return response;

44
apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts

@ -1,16 +1,3 @@
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '@ghostfolio/api/services/data-provider/interfaces/data-provider.interface';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '@ghostfolio/api/services/interfaces/interfaces';
import { DEFAULT_CURRENCY } from '@ghostfolio/common/config';
import { DATE_FORMAT, parseDate } from '@ghostfolio/common/helper';
import { DataProviderInfo } from '@ghostfolio/common/interfaces';
@ -20,6 +7,20 @@ import { DataSource, SymbolProfile } from '@prisma/client';
import { format, isAfter, isBefore, isSameDay } from 'date-fns';
import got from 'got';
import { LookupItem } from '../../../app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '../../configuration/configuration.service';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '../../interfaces/interfaces';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '../interfaces/data-provider.interface';
@Injectable()
export class FinancialModelingPrepService implements DataProviderInterface {
private apiKey: string;
@ -65,9 +66,9 @@ export class FinancialModelingPrepService implements DataProviderInterface {
requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'),
symbol,
to
}: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}> {
}: GetHistoricalParams): Promise<
Record<string, Record<string, IDataProviderHistoricalResponse>>
> {
try {
const abortController = new AbortController();
@ -83,9 +84,10 @@ export class FinancialModelingPrepService implements DataProviderInterface {
}
).json<any>();
const result: {
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
} = {
const result: Record<
string,
Record<string, IDataProviderHistoricalResponse>
> = {
[symbol]: {}
};
@ -119,8 +121,8 @@ export class FinancialModelingPrepService implements DataProviderInterface {
public async getQuotes({
requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'),
symbols
}: GetQuotesParams): Promise<{ [symbol: string]: IDataProviderResponse }> {
const response: { [symbol: string]: IDataProviderResponse } = {};
}: GetQuotesParams): Promise<Record<string, IDataProviderResponse>> {
const response: Record<string, IDataProviderResponse> = {};
if (symbols.length <= 0) {
return response;

46
apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts

@ -1,18 +1,3 @@
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '@ghostfolio/api/services/data-provider/interfaces/data-provider.interface';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '@ghostfolio/api/services/interfaces/interfaces';
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service';
import { DATE_FORMAT, parseDate } from '@ghostfolio/common/helper';
import { DataProviderInfo } from '@ghostfolio/common/interfaces';
@ -21,6 +6,22 @@ import { DataSource, SymbolProfile } from '@prisma/client';
import { format } from 'date-fns';
import { GoogleSpreadsheet } from 'google-spreadsheet';
import { LookupItem } from '../../../app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '../../configuration/configuration.service';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '../../interfaces/interfaces';
import { PrismaService } from '../../prisma/prisma.service';
import { SymbolProfileService } from '../../symbol-profile/symbol-profile.service';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '../interfaces/data-provider.interface';
@Injectable()
export class GoogleSheetsService implements DataProviderInterface {
public constructor(
@ -60,9 +61,9 @@ export class GoogleSheetsService implements DataProviderInterface {
from,
symbol,
to
}: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}> {
}: GetHistoricalParams): Promise<
Record<string, Record<string, IDataProviderHistoricalResponse>>
> {
try {
const sheet = await this.getSheet({
symbol,
@ -71,9 +72,8 @@ export class GoogleSheetsService implements DataProviderInterface {
const rows = await sheet.getRows();
const historicalData: {
[date: string]: IDataProviderHistoricalResponse;
} = {};
const historicalData: Record<string, IDataProviderHistoricalResponse> =
{};
rows
.filter((_row, index) => {
@ -105,8 +105,8 @@ export class GoogleSheetsService implements DataProviderInterface {
public async getQuotes({
symbols
}: GetQuotesParams): Promise<{ [symbol: string]: IDataProviderResponse }> {
const response: { [symbol: string]: IDataProviderResponse } = {};
}: GetQuotesParams): Promise<Record<string, IDataProviderResponse>> {
const response: Record<string, IDataProviderResponse> = {};
if (symbols.length <= 0) {
return response;

30
apps/api/src/services/data-provider/interfaces/data-provider.interface.ts

@ -1,13 +1,14 @@
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '@ghostfolio/api/services/interfaces/interfaces';
import { DataProviderInfo } from '@ghostfolio/common/interfaces';
import { Granularity } from '@ghostfolio/common/types';
import { DataSource, SymbolProfile } from '@prisma/client';
import { LookupItem } from '../../../app/symbol/interfaces/lookup-item.interface';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '../../interfaces/interfaces';
export interface DataProviderInterface {
canHandle(symbol: string): boolean;
@ -19,9 +20,14 @@ export interface DataProviderInterface {
getDataProviderInfo(): DataProviderInfo;
getDividends({ from, granularity, symbol, to }: GetDividendsParams): Promise<{
[date: string]: IDataProviderHistoricalResponse;
}>;
getDividends({
from,
granularity,
symbol,
to
}: GetDividendsParams): Promise<
Record<string, IDataProviderHistoricalResponse>
>;
getHistorical({
from,
@ -29,9 +35,9 @@ export interface DataProviderInterface {
requestTimeout,
symbol,
to
}: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}>; // TODO: Return only one symbol
}: GetHistoricalParams): Promise<
Record<string, Record<string, IDataProviderHistoricalResponse>>
>; // TODO: Return only one symbol
getMaxNumberOfSymbolsPerRequest?(): number;
@ -40,7 +46,7 @@ export interface DataProviderInterface {
getQuotes({
requestTimeout,
symbols
}: GetQuotesParams): Promise<{ [symbol: string]: IDataProviderResponse }>;
}: GetQuotesParams): Promise<Record<string, IDataProviderResponse>>;
getTestSymbol(): string;

48
apps/api/src/services/data-provider/manual/manual.service.ts

@ -1,18 +1,3 @@
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '@ghostfolio/api/services/data-provider/interfaces/data-provider.interface';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '@ghostfolio/api/services/interfaces/interfaces';
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service';
import {
DATE_FORMAT,
extractNumberFromString,
@ -31,6 +16,22 @@ import { addDays, format, isBefore } from 'date-fns';
import got, { Headers } from 'got';
import jsonpath from 'jsonpath';
import { LookupItem } from '../../../app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '../../configuration/configuration.service';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '../../interfaces/interfaces';
import { PrismaService } from '../../prisma/prisma.service';
import { SymbolProfileService } from '../../symbol-profile/symbol-profile.service';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '../interfaces/data-provider.interface';
@Injectable()
export class ManualService implements DataProviderInterface {
public constructor(
@ -79,9 +80,9 @@ export class ManualService implements DataProviderInterface {
from,
symbol,
to
}: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}> {
}: GetHistoricalParams): Promise<
Record<string, Record<string, IDataProviderHistoricalResponse>>
> {
try {
const [symbolProfile] = await this.symbolProfileService.getSymbolProfiles(
[{ symbol, dataSource: this.getName() }]
@ -90,9 +91,10 @@ export class ManualService implements DataProviderInterface {
symbolProfile?.scraperConfiguration ?? {};
if (defaultMarketPrice) {
const historical: {
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
} = {
const historical: Record<
string,
Record<string, IDataProviderHistoricalResponse>
> = {
[symbol]: {}
};
let date = from;
@ -135,8 +137,8 @@ export class ManualService implements DataProviderInterface {
public async getQuotes({
symbols
}: GetQuotesParams): Promise<{ [symbol: string]: IDataProviderResponse }> {
const response: { [symbol: string]: IDataProviderResponse } = {};
}: GetQuotesParams): Promise<Record<string, IDataProviderResponse>> {
const response: Record<string, IDataProviderResponse> = {};
if (symbols.length <= 0) {
return response;

35
apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts

@ -1,16 +1,3 @@
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '@ghostfolio/api/services/data-provider/interfaces/data-provider.interface';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '@ghostfolio/api/services/interfaces/interfaces';
import { ghostfolioFearAndGreedIndexSymbol } from '@ghostfolio/common/config';
import { DATE_FORMAT, getYesterday } from '@ghostfolio/common/helper';
import { DataProviderInfo } from '@ghostfolio/common/interfaces';
@ -20,6 +7,20 @@ import { DataSource, SymbolProfile } from '@prisma/client';
import { format } from 'date-fns';
import got from 'got';
import { LookupItem } from '../../../app/symbol/interfaces/lookup-item.interface';
import { ConfigurationService } from '../../configuration/configuration.service';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '../../interfaces/interfaces';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '../interfaces/data-provider.interface';
@Injectable()
export class RapidApiService implements DataProviderInterface {
public constructor(
@ -57,9 +58,9 @@ export class RapidApiService implements DataProviderInterface {
from,
symbol,
to
}: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}> {
}: GetHistoricalParams): Promise<
Record<string, Record<string, IDataProviderHistoricalResponse>>
> {
try {
if (symbol === ghostfolioFearAndGreedIndexSymbol) {
const fgi = await this.getFearAndGreedIndex();
@ -90,7 +91,7 @@ export class RapidApiService implements DataProviderInterface {
public async getQuotes({
symbols
}: GetQuotesParams): Promise<{ [symbol: string]: IDataProviderResponse }> {
}: GetQuotesParams): Promise<Record<string, IDataProviderResponse>> {
if (symbols.length <= 0) {
return {};
}

50
apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts

@ -1,17 +1,3 @@
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { CryptocurrencyService } from '@ghostfolio/api/services/cryptocurrency/cryptocurrency.service';
import { YahooFinanceDataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '@ghostfolio/api/services/data-provider/interfaces/data-provider.interface';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '@ghostfolio/api/services/interfaces/interfaces';
import { DEFAULT_CURRENCY } from '@ghostfolio/common/config';
import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { DataProviderInfo } from '@ghostfolio/common/interfaces';
@ -27,6 +13,21 @@ import {
} from 'yahoo-finance2/dist/esm/src/modules/historical';
import { Quote } from 'yahoo-finance2/dist/esm/src/modules/quote';
import { LookupItem } from '../../../app/symbol/interfaces/lookup-item.interface';
import { CryptocurrencyService } from '../../cryptocurrency/cryptocurrency.service';
import {
IDataProviderHistoricalResponse,
IDataProviderResponse
} from '../../interfaces/interfaces';
import { YahooFinanceDataEnhancerService } from '../data-enhancer/yahoo-finance/yahoo-finance.service';
import {
DataProviderInterface,
GetDividendsParams,
GetHistoricalParams,
GetQuotesParams,
GetSearchParams
} from '../interfaces/data-provider.interface';
@Injectable()
export class YahooFinanceService implements DataProviderInterface {
public constructor(
@ -78,9 +79,7 @@ export class YahooFinanceService implements DataProviderInterface {
}
)
);
const response: {
[date: string]: IDataProviderHistoricalResponse;
} = {};
const response: Record<string, IDataProviderHistoricalResponse> = {};
for (const historicalItem of historicalResult) {
response[format(historicalItem.date, DATE_FORMAT)] = {
@ -106,9 +105,9 @@ export class YahooFinanceService implements DataProviderInterface {
from,
symbol,
to
}: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}> {
}: GetHistoricalParams): Promise<
Record<string, Record<string, IDataProviderHistoricalResponse>>
> {
if (isSameDay(from, to)) {
to = addDays(to, 1);
}
@ -127,9 +126,10 @@ export class YahooFinanceService implements DataProviderInterface {
)
);
const response: {
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
} = {};
const response: Record<
string,
Record<string, IDataProviderHistoricalResponse>
> = {};
response[symbol] = {};
@ -160,8 +160,8 @@ export class YahooFinanceService implements DataProviderInterface {
public async getQuotes({
symbols
}: GetQuotesParams): Promise<{ [symbol: string]: IDataProviderResponse }> {
const response: { [symbol: string]: IDataProviderResponse } = {};
}: GetQuotesParams): Promise<Record<string, IDataProviderResponse>> {
const response: Record<string, IDataProviderResponse> = {};
if (symbols.length <= 0) {
return response;

29
apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts

@ -1,9 +1,3 @@
import { LogPerformance } from '@ghostfolio/api/interceptors/performance-logging/performance-logging.interceptor';
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces';
import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service';
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { PropertyService } from '@ghostfolio/api/services/property/property.service';
import {
DEFAULT_CURRENCY,
DERIVED_CURRENCIES,
@ -26,11 +20,18 @@ import {
import { isNumber, uniq } from 'lodash';
import ms from 'ms';
import { LogPerformance } from '../../interceptors/performance-logging/performance-logging.interceptor';
import { DataProviderService } from '../data-provider/data-provider.service';
import { IDataGatheringItem } from '../interfaces/interfaces';
import { MarketDataService } from '../market-data/market-data.service';
import { PrismaService } from '../prisma/prisma.service';
import { PropertyService } from '../property/property.service';
@Injectable()
export class ExchangeRateDataService {
private currencies: string[] = [];
private currencyPairs: IDataGatheringItem[] = [];
private exchangeRates: { [currencyPair: string]: number } = {};
private exchangeRates: Record<string, number> = {};
public constructor(
private readonly dataProviderService: DataProviderService,
@ -63,9 +64,7 @@ export class ExchangeRateDataService {
return {};
}
const exchangeRatesByCurrency: {
[currency: string]: { [dateString: string]: number };
} = {};
const exchangeRatesByCurrency: Record<string, Record<string, number>> = {};
for (const currency of currencies) {
exchangeRatesByCurrency[`${currency}${targetCurrency}`] =
@ -351,7 +350,7 @@ export class ExchangeRateDataService {
startDate: Date;
}) {
const dates = eachDayOfInterval({ end: endDate, start: startDate });
const factors: { [dateString: string]: number } = {};
const factors: Record<string, number> = {};
if (currencyFrom === currencyTo) {
for (const date of dates) {
@ -379,12 +378,8 @@ export class ExchangeRateDataService {
} else {
// Calculate indirectly via base currency
const marketPriceBaseCurrencyFromCurrency: {
[dateString: string]: number;
} = {};
const marketPriceBaseCurrencyToCurrency: {
[dateString: string]: number;
} = {};
const marketPriceBaseCurrencyFromCurrency: Record<string, number> = {};
const marketPriceBaseCurrencyToCurrency: Record<string, number> = {};
try {
if (currencyFrom === DEFAULT_CURRENCY) {

2
apps/api/src/services/i18n/i18n.service.ts

@ -7,7 +7,7 @@ import { join } from 'path';
export class I18nService {
private localesPath = join(__dirname, 'assets', 'locales');
private translations: { [locale: string]: cheerio.CheerioAPI } = {};
private translations: Record<string, cheerio.CheerioAPI> = {};
public constructor() {
this.loadFiles();

4
apps/api/src/services/property/property.service.ts

@ -17,9 +17,7 @@ export class PropertyService {
}
public async get() {
const response: {
[key: string]: boolean | object | string | string[];
} = {
const response: Record<string, boolean | object | string | string[]> = {
[PROPERTY_CURRENCIES]: []
};

2
apps/api/src/services/queues/data-gathering/data-gathering.service.ts

@ -395,7 +395,7 @@ export class DataGatheringService {
}
private async getSymbolsMax(): Promise<IDataGatheringItem[]> {
const benchmarkAssetProfileIdMap: { [key: string]: boolean } = {};
const benchmarkAssetProfileIdMap: Record<string, boolean> = {};
(
((await this.propertyService.getByKey(
PROPERTY_BENCHMARKS

6
apps/api/src/services/symbol-profile/symbol-profile.service.ts

@ -299,10 +299,6 @@ export class SymbolProfileService {
}
private getSymbolMapping(symbolProfile: SymbolProfile) {
return (
(symbolProfile['symbolMapping'] as {
[key: string]: string;
}) ?? {}
);
return (symbolProfile['symbolMapping'] as Record<string, string>) ?? {};
}
}

11
apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.ts

@ -1,4 +1,3 @@
import { UserService } from '@ghostfolio/client/services/user/user.service';
import {
DATE_FORMAT,
getDateFormatString,
@ -32,6 +31,7 @@ import { first, last } from 'lodash';
import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject, takeUntil } from 'rxjs';
import { UserService } from '../../services/user/user.service';
import { MarketDataDetailDialogParams } from './market-data-detail-dialog/interfaces/interfaces';
import { MarketDataDetailDialog } from './market-data-detail-dialog/market-data-detail-dialog.component';
@ -55,11 +55,10 @@ export class AdminMarketDataDetailComponent implements OnChanges {
public defaultDateFormat: string;
public deviceType: string;
public historicalDataItems: LineChartItem[];
public marketDataByMonth: {
[yearMonth: string]: {
[day: string]: Pick<MarketData, 'date' | 'marketPrice'> & { day: number };
};
} = {};
public marketDataByMonth: Record<
string,
Record<string, Pick<MarketData, 'date' | 'marketPrice'> & { day: number }>
> = {};
public user: User;
private unsubscribeSubject = new Subject<void>();

8
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts

@ -70,16 +70,12 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
});
public assetProfileSubClass: string;
public benchmarks: Partial<SymbolProfile>[];
public countries: {
[code: string]: { name: string; value: number };
};
public countries: Record<string, { name: string; value: number }>;
public currencies: string[] = [];
public ghostfolioScraperApiSymbolPrefix = ghostfolioScraperApiSymbolPrefix;
public isBenchmark = false;
public marketDataDetails: MarketData[] = [];
public sectors: {
[name: string]: { name: string; value: number };
};
public sectors: Record<string, { name: string; value: number }>;
private static readonly HISTORICAL_DATA_TEMPLATE = `date;marketPrice\n${format(
new Date(),

8
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts

@ -94,9 +94,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
public assetSubClass: string;
public averagePrice: number;
public benchmarkDataItems: LineChartItem[];
public countries: {
[code: string]: { name: string; value: number };
};
public countries: Record<string, { name: string; value: number }>;
public dataProviderInfo: DataProviderInfo;
public dataSource: MatTableDataSource<Activity>;
public dividendInBaseCurrency: number;
@ -120,9 +118,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
public quantity: number;
public quantityPrecision = 2;
public reportDataGlitchMail: string;
public sectors: {
[name: string]: { name: string; value: number };
};
public sectors: Record<string, { name: string; value: number }>;
public separatorKeysCodes: number[] = [COMMA, ENTER];
public sortColumn = 'date';
public sortDirection: SortDirection = 'desc';

2
apps/client/src/app/components/world-map-chart/world-map-chart.component.ts

@ -17,7 +17,7 @@ import svgMap from 'svgmap';
styleUrls: ['./world-map-chart.component.scss']
})
export class WorldMapChartComponent implements OnChanges, OnDestroy {
@Input() countries: { [code: string]: { name?: string; value: number } };
@Input() countries: Record<string, { name?: string; value: number }>;
@Input() format: string;
@Input() isInPercent = false;
@Input() locale = getLocale();

4
apps/client/src/app/pages/landing/landing-page.component.ts

@ -14,9 +14,7 @@ import { Subject } from 'rxjs';
templateUrl: './landing-page.html'
})
export class LandingPageComponent implements OnDestroy, OnInit {
public countriesOfSubscribersMap: {
[code: string]: { value: number };
} = {};
public countriesOfSubscribersMap: Record<string, { value: number }> = {};
public currentYear = format(new Date(), 'yyyy');
public deviceType: string;
public hasPermissionForDemo: boolean;

63
apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts

@ -1,8 +1,3 @@
import { AccountDetailDialog } from '@ghostfolio/client/components/account-detail-dialog/account-detail-dialog.component';
import { AccountDetailDialogParams } from '@ghostfolio/client/components/account-detail-dialog/interfaces/interfaces';
import { DataService } from '@ghostfolio/client/services/data.service';
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { MAX_TOP_HOLDINGS, UNKNOWN_KEY } from '@ghostfolio/common/config';
import { prettifySymbol } from '@ghostfolio/common/helper';
import {
@ -25,24 +20,27 @@ import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { AccountDetailDialog } from '../../../components/account-detail-dialog/account-detail-dialog.component';
import { AccountDetailDialogParams } from '../../../components/account-detail-dialog/interfaces/interfaces';
import { DataService } from '../../../services/data.service';
import { ImpersonationStorageService } from '../../../services/impersonation-storage.service';
import { UserService } from '../../../services/user/user.service';
@Component({
selector: 'gf-allocations-page',
styleUrls: ['./allocations-page.scss'],
templateUrl: './allocations-page.html'
})
export class AllocationsPageComponent implements OnDestroy, OnInit {
public accounts: {
[id: string]: Pick<Account, 'name'> & {
public accounts: Record<
string,
Pick<Account, 'name'> & {
id: string;
value: number;
};
};
public continents: {
[code: string]: { name: string; value: number };
};
public countries: {
[code: string]: { name: string; value: number };
};
}
>;
public continents: Record<string, { name: string; value: number }>;
public countries: Record<string, { name: string; value: number }>;
public deviceType: string;
public hasImpersonationId: boolean;
public isLoading = false;
@ -56,15 +54,17 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
value: number;
};
};
public platforms: {
[id: string]: Pick<Platform, 'name'> & {
public platforms: Record<
string,
Pick<Platform, 'name'> & {
id: string;
value: number;
};
};
}
>;
public portfolioDetails: PortfolioDetails;
public positions: {
[symbol: string]: Pick<
public positions: Record<
string,
Pick<
PortfolioPosition,
| 'assetClass'
| 'assetClassLabel'
@ -73,23 +73,20 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
| 'currency'
| 'exchange'
| 'name'
> & { etfProvider: string; value: number };
};
public sectors: {
[name: string]: { name: string; value: number };
};
public symbols: {
[name: string]: {
> & { etfProvider: string; value: number }
>;
public sectors: Record<string, { name: string; value: number }>;
public symbols: Record<
string,
{
dataSource?: DataSource;
name: string;
symbol: string;
value: number;
};
};
}
>;
public topHoldings: Holding[];
public topHoldingsMap: {
[name: string]: { name: string; value: number };
};
public topHoldingsMap: Record<string, { name: string; value: number }>;
public totalValueInEtf = 0;
public UNKNOWN_KEY = UNKNOWN_KEY;
public user: User;

31
apps/client/src/app/pages/public/public-page.component.ts

@ -1,4 +1,3 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { UNKNOWN_KEY } from '@ghostfolio/common/config';
import { prettifySymbol } from '@ghostfolio/common/helper';
import {
@ -16,6 +15,8 @@ import { DeviceDetectorService } from 'ngx-device-detector';
import { EMPTY, Subject } from 'rxjs';
import { catchError, takeUntil } from 'rxjs/operators';
import { DataService } from '../../services/data.service';
@Component({
host: { class: 'page' },
selector: 'gf-public-page',
@ -23,29 +24,25 @@ import { catchError, takeUntil } from 'rxjs/operators';
templateUrl: './public-page.html'
})
export class PublicPageComponent implements OnInit {
public continents: {
[code: string]: { name: string; value: number };
};
public countries: {
[code: string]: { name: string; value: number };
};
public continents: Record<string, { name: string; value: number }>;
public countries: Record<string, { name: string; value: number }>;
public deviceType: string;
public holdings: PublicPortfolioResponse['holdings'][string][];
public markets: {
[key in Market]: { id: Market; valueInPercentage: number };
};
public positions: {
[symbol: string]: Pick<PortfolioPosition, 'currency' | 'name'> & {
public positions: Record<
string,
Pick<PortfolioPosition, 'currency' | 'name'> & {
value: number;
};
};
}
>;
public publicPortfolioDetails: PublicPortfolioResponse;
public sectors: {
[name: string]: { name: string; value: number };
};
public symbols: {
[name: string]: { name: string; symbol: string; value: number };
};
public sectors: Record<string, { name: string; value: number }>;
public symbols: Record<
string,
{ name: string; symbol: string; value: number }
>;
public UNKNOWN_KEY = UNKNOWN_KEY;
private accessId: string;

8
libs/common/src/lib/class-transformer.ts

@ -3,11 +3,9 @@ import { Big } from 'big.js';
export function transformToMapOfBig({
value
}: {
value: { [key: string]: string };
}): {
[key: string]: Big;
} {
const mapOfBig: { [key: string]: Big } = {};
value: Record<string, string>;
}): Record<string, Big> {
const mapOfBig: Record<string, Big> = {};
for (const key in value) {
mapOfBig[key] = new Big(value[key]);

2
libs/common/src/lib/interfaces/admin-data.interface.ts

@ -6,7 +6,7 @@ export interface AdminData {
label2: string;
value: number;
} & AssetProfileIdentifier)[];
settings: { [key: string]: boolean | object | string | string[] };
settings: Record<string, boolean | object | string | string[]>;
transactionCount: number;
userCount: number;
version: string;

2
libs/common/src/lib/interfaces/enhanced-symbol-profile.interface.ts

@ -27,7 +27,7 @@ export interface EnhancedSymbolProfile {
scraperConfiguration?: ScraperConfiguration;
sectors: Sector[];
symbol: string;
symbolMapping?: { [key: string]: string };
symbolMapping?: Record<string, string>;
updatedAt: Date;
url?: string;
}

20
libs/common/src/lib/interfaces/portfolio-details.interface.ts

@ -5,16 +5,17 @@ import {
import { Market, MarketAdvanced } from '@ghostfolio/common/types';
export interface PortfolioDetails {
accounts: {
[id: string]: {
accounts: Record<
string,
{
balance: number;
currency: string;
name: string;
valueInBaseCurrency: number;
valueInPercentage?: number;
};
};
holdings: { [symbol: string]: PortfolioPosition };
}
>;
holdings: Record<string, PortfolioPosition>;
markets?: {
[key in Market]: {
id: Market;
@ -29,14 +30,15 @@ export interface PortfolioDetails {
valueInPercentage: number;
};
};
platforms: {
[id: string]: {
platforms: Record<
string,
{
balance: number;
currency: string;
name: string;
valueInBaseCurrency: number;
valueInPercentage?: number;
};
};
}
>;
summary?: PortfolioSummary;
}

2
libs/common/src/lib/interfaces/portfolio-item.interface.ts

@ -4,6 +4,6 @@ export interface PortfolioItem {
date: string;
grossPerformancePercent: number;
investment: number;
positions: { [symbol: string]: Position };
positions: Record<string, Position>;
value: number;
}

2
libs/common/src/lib/interfaces/portfolio-report.interface.ts

@ -1,5 +1,5 @@
import { PortfolioReportRule } from './portfolio-report-rule.interface';
export interface PortfolioReport {
rules: { [group: string]: PortfolioReportRule[] };
rules: Record<string, PortfolioReportRule[]>;
}

9
libs/common/src/lib/interfaces/responses/public-portfolio-response.interface.ts

@ -4,8 +4,9 @@ import { Market } from '../../types';
export interface PublicPortfolioResponse extends PublicPortfolioResponseV1 {
alias?: string;
hasDetails: boolean;
holdings: {
[symbol: string]: Pick<
holdings: Record<
string,
Pick<
PortfolioPosition,
| 'allocationInPercentage'
| 'assetClass'
@ -21,8 +22,8 @@ export interface PublicPortfolioResponse extends PublicPortfolioResponseV1 {
| 'url'
| 'valueInBaseCurrency'
| 'valueInPercentage'
>;
};
>
>;
markets: {
[key in Market]: Pick<
PortfolioDetails['markets'][key],

2
libs/common/src/lib/interfaces/scraper-configuration.interface.ts

@ -1,6 +1,6 @@
export interface ScraperConfiguration {
defaultMarketPrice?: number;
headers?: { [key: string]: string };
headers?: Record<string, string>;
locale?: string;
mode?: 'instant' | 'lazy';
selector: string;

38
libs/common/src/lib/interfaces/symbol-metrics.interface.ts

@ -3,12 +3,8 @@ import { DateRange } from '@ghostfolio/common/types';
import { Big } from 'big.js';
export interface SymbolMetrics {
currentValues: {
[date: string]: Big;
};
currentValuesWithCurrencyEffect: {
[date: string]: Big;
};
currentValues: Record<string, Big>;
currentValuesWithCurrencyEffect: Record<string, Big>;
feesWithCurrencyEffect: Big;
grossPerformance: Big;
grossPerformancePercentage: Big;
@ -17,30 +13,18 @@ export interface SymbolMetrics {
hasErrors: boolean;
initialValue: Big;
initialValueWithCurrencyEffect: Big;
investmentValuesAccumulated: {
[date: string]: Big;
};
investmentValuesAccumulatedWithCurrencyEffect: {
[date: string]: Big;
};
investmentValuesWithCurrencyEffect: {
[date: string]: Big;
};
investmentValuesAccumulated: Record<string, Big>;
investmentValuesAccumulatedWithCurrencyEffect: Record<string, Big>;
investmentValuesWithCurrencyEffect: Record<string, Big>;
netPerformance: Big;
netPerformancePercentage: Big;
netPerformancePercentageWithCurrencyEffectMap: { [key: DateRange]: Big };
netPerformanceValues: {
[date: string]: Big;
};
netPerformanceValuesWithCurrencyEffect: { [date: string]: Big };
netPerformanceWithCurrencyEffectMap: { [key: DateRange]: Big };
netPerformancePercentageWithCurrencyEffectMap: Record<DateRange, Big>;
netPerformanceValues: Record<string, Big>;
netPerformanceValuesWithCurrencyEffect: Record<string, Big>;
netPerformanceWithCurrencyEffectMap: Record<DateRange, Big>;
timeWeightedInvestment: Big;
timeWeightedInvestmentValues: {
[date: string]: Big;
};
timeWeightedInvestmentValuesWithCurrencyEffect: {
[date: string]: Big;
};
timeWeightedInvestmentValues: Record<string, Big>;
timeWeightedInvestmentValuesWithCurrencyEffect: Record<string, Big>;
timeWeightedInvestmentWithCurrencyEffect: Big;
totalAccountBalanceInBaseCurrency: Big;
totalDividend: Big;

4
libs/common/src/lib/models/timeline-position.ts

@ -70,10 +70,10 @@ export class TimelinePosition {
netPerformancePercentage: Big;
@Transform(transformToMapOfBig, { toClassOnly: true })
netPerformancePercentageWithCurrencyEffectMap: { [key: DateRange]: Big };
netPerformancePercentageWithCurrencyEffectMap: Record<DateRange, Big>;
@Transform(transformToMapOfBig, { toClassOnly: true })
netPerformanceWithCurrencyEffectMap: { [key: DateRange]: Big };
netPerformanceWithCurrencyEffectMap: Record<DateRange, Big>;
@Transform(transformToBig, { toClassOnly: true })
@Type(() => Big)

2
libs/ui/src/lib/assistant/assistant.component.ts

@ -292,7 +292,7 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
}
}
public hasFilter(aFormValue: { [key: string]: string }) {
public hasFilter(aFormValue: Record<string, string>) {
return Object.values(aFormValue).some((value) => {
return !!value;
});

24
libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts

@ -66,13 +66,14 @@ export class GfPortfolioProportionChartComponent
@Input() locale = getLocale();
@Input() maxItems?: number;
@Input() showLabels = false;
@Input() positions: {
[symbol: string]: Pick<PortfolioPosition, 'type'> & {
@Input() positions: Record<
string,
Pick<PortfolioPosition, 'type'> & {
dataSource?: DataSource;
name: string;
value: number;
};
} = {};
}
> = {};
@Output() proportionChartClicked = new EventEmitter<AssetProfileIdentifier>();
@ -83,9 +84,7 @@ export class GfPortfolioProportionChartComponent
private readonly OTHER_KEY = 'OTHER';
private colorMap: {
[symbol: string]: string;
} = {};
private colorMap: Record<string, string> = {};
public constructor() {
Chart.register(ArcElement, DoughnutController, LinearScale, Tooltip);
@ -109,14 +108,15 @@ export class GfPortfolioProportionChartComponent
private initialize() {
this.isLoading = true;
const chartData: {
[symbol: string]: {
const chartData: Record<
string,
{
color?: string;
name: string;
subCategory?: { [symbol: string]: { value: Big } };
subCategory?: Record<string, { value: Big }>;
value: Big;
};
} = {};
}
> = {};
this.colorMap = {
[this.OTHER_KEY]: `rgba(${getTextColor(this.colorScheme)}, 0.24)`,
[UNKNOWN_KEY]: `rgba(${getTextColor(this.colorScheme)}, 0.12)`

Loading…
Cancel
Save