|
|
@ -20,12 +20,13 @@ import {
|
|
|
|
|
|
|
|
|
|
|
|
import { Injectable, Logger } from '@nestjs/common';
|
|
|
|
import { Injectable, Logger } from '@nestjs/common';
|
|
|
|
import { DataSource, SymbolProfile } from '@prisma/client';
|
|
|
|
import { DataSource, SymbolProfile } from '@prisma/client';
|
|
|
|
|
|
|
|
import { isISIN } from 'class-validator';
|
|
|
|
import { format, isAfter, isBefore, isSameDay } from 'date-fns';
|
|
|
|
import { format, isAfter, isBefore, isSameDay } from 'date-fns';
|
|
|
|
|
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
@Injectable()
|
|
|
|
export class FinancialModelingPrepService implements DataProviderInterface {
|
|
|
|
export class FinancialModelingPrepService implements DataProviderInterface {
|
|
|
|
private apiKey: string;
|
|
|
|
private apiKey: string;
|
|
|
|
private readonly URL = 'https://financialmodelingprep.com/api/v3';
|
|
|
|
private readonly URL = this.getUrl({ version: 3 });
|
|
|
|
|
|
|
|
|
|
|
|
public constructor(
|
|
|
|
public constructor(
|
|
|
|
private readonly configurationService: ConfigurationService
|
|
|
|
private readonly configurationService: ConfigurationService
|
|
|
@ -161,25 +162,49 @@ export class FinancialModelingPrepService implements DataProviderInterface {
|
|
|
|
let items: LookupItem[] = [];
|
|
|
|
let items: LookupItem[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const result = await fetch(
|
|
|
|
if (isISIN(query)) {
|
|
|
|
`${this.URL}/search?query=${query}&apikey=${this.apiKey}`,
|
|
|
|
const result = await fetch(
|
|
|
|
{
|
|
|
|
`${this.getUrl({ version: 4 })}/search/isin?isin=${query}&apikey=${this.apiKey}`,
|
|
|
|
signal: AbortSignal.timeout(
|
|
|
|
{
|
|
|
|
this.configurationService.get('REQUEST_TIMEOUT')
|
|
|
|
signal: AbortSignal.timeout(
|
|
|
|
)
|
|
|
|
this.configurationService.get('REQUEST_TIMEOUT')
|
|
|
|
}
|
|
|
|
)
|
|
|
|
).then((res) => res.json());
|
|
|
|
}
|
|
|
|
|
|
|
|
).then((res) => res.json());
|
|
|
|
items = result.map(({ currency, name, symbol }) => {
|
|
|
|
|
|
|
|
return {
|
|
|
|
items = result.map(({ companyName, currency, symbol }) => {
|
|
|
|
// TODO: Add assetClass
|
|
|
|
return {
|
|
|
|
// TODO: Add assetSubClass
|
|
|
|
currency,
|
|
|
|
currency,
|
|
|
|
symbol,
|
|
|
|
name,
|
|
|
|
assetClass: undefined, // TODO
|
|
|
|
symbol,
|
|
|
|
assetSubClass: undefined, // TODO
|
|
|
|
dataSource: this.getName()
|
|
|
|
dataProviderInfo: this.getDataProviderInfo(),
|
|
|
|
};
|
|
|
|
dataSource: this.getName(),
|
|
|
|
});
|
|
|
|
name: companyName
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
const result = await fetch(
|
|
|
|
|
|
|
|
`${this.URL}/search?query=${query}&apikey=${this.apiKey}`,
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
signal: AbortSignal.timeout(
|
|
|
|
|
|
|
|
this.configurationService.get('REQUEST_TIMEOUT')
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
).then((res) => res.json());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
items = result.map(({ currency, name, symbol }) => {
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
currency,
|
|
|
|
|
|
|
|
name,
|
|
|
|
|
|
|
|
symbol,
|
|
|
|
|
|
|
|
assetClass: undefined, // TODO
|
|
|
|
|
|
|
|
assetSubClass: undefined, // TODO
|
|
|
|
|
|
|
|
dataProviderInfo: this.getDataProviderInfo(),
|
|
|
|
|
|
|
|
dataSource: this.getName()
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
} catch (error) {
|
|
|
|
let message = error;
|
|
|
|
let message = error;
|
|
|
|
|
|
|
|
|
|
|
@ -194,4 +219,8 @@ export class FinancialModelingPrepService implements DataProviderInterface {
|
|
|
|
|
|
|
|
|
|
|
|
return { items };
|
|
|
|
return { items };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private getUrl({ version }: { version: number }) {
|
|
|
|
|
|
|
|
return `https://financialmodelingprep.com/api/v${version}`;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|