diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..496ee2ca
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.DS_Store
\ No newline at end of file
diff --git a/fullstack/task/.yarn/cache/esbuild-darwin-64-npm-0.15.18-c3c12de20e-8.zip b/fullstack/task/.yarn/cache/esbuild-darwin-64-npm-0.15.18-c3c12de20e-8.zip
deleted file mode 100644
index be89e66c..00000000
Binary files a/fullstack/task/.yarn/cache/esbuild-darwin-64-npm-0.15.18-c3c12de20e-8.zip and /dev/null differ
diff --git a/fullstack/task/.yarn/cache/esbuild-darwin-arm64-npm-0.15.18-37bdbfa731-8.zip b/fullstack/task/.yarn/cache/esbuild-darwin-arm64-npm-0.15.18-37bdbfa731-8.zip
new file mode 100644
index 00000000..5fa96fd3
Binary files /dev/null and b/fullstack/task/.yarn/cache/esbuild-darwin-arm64-npm-0.15.18-37bdbfa731-8.zip differ
diff --git a/fullstack/task/.yarn/cache/esbuild-linux-64-npm-0.15.18-b7675c5a72-8.zip b/fullstack/task/.yarn/cache/esbuild-linux-64-npm-0.15.18-b7675c5a72-8.zip
deleted file mode 100644
index 86ff108e..00000000
Binary files a/fullstack/task/.yarn/cache/esbuild-linux-64-npm-0.15.18-b7675c5a72-8.zip and /dev/null differ
diff --git a/fullstack/task/.yarn/cache/esbuild-linux-arm64-npm-0.15.18-16f8e6f421-8.zip b/fullstack/task/.yarn/cache/esbuild-linux-arm64-npm-0.15.18-16f8e6f421-8.zip
new file mode 100644
index 00000000..906abfa1
Binary files /dev/null and b/fullstack/task/.yarn/cache/esbuild-linux-arm64-npm-0.15.18-16f8e6f421-8.zip differ
diff --git a/fullstack/task/.yarn/cache/esbuild-windows-64-npm-0.15.18-f926268f42-8.zip b/fullstack/task/.yarn/cache/esbuild-windows-64-npm-0.15.18-f926268f42-8.zip
deleted file mode 100644
index 5748da7e..00000000
Binary files a/fullstack/task/.yarn/cache/esbuild-windows-64-npm-0.15.18-f926268f42-8.zip and /dev/null differ
diff --git a/fullstack/task/.yarn/cache/esbuild-windows-arm64-npm-0.15.18-ca93639f32-8.zip b/fullstack/task/.yarn/cache/esbuild-windows-arm64-npm-0.15.18-ca93639f32-8.zip
new file mode 100644
index 00000000..42a38754
Binary files /dev/null and b/fullstack/task/.yarn/cache/esbuild-windows-arm64-npm-0.15.18-ca93639f32-8.zip differ
diff --git a/fullstack/task/packages/client/project.json b/fullstack/task/packages/client/project.json
index e1bd7894..265a5ca4 100644
--- a/fullstack/task/packages/client/project.json
+++ b/fullstack/task/packages/client/project.json
@@ -9,7 +9,7 @@
"start": {
"executor": "nx:run-commands",
"options": {
- "command": "yarn vite",
+ "command": "yarn vite --host 0.0.0.0",
"cwd": "packages/client"
}
},
diff --git a/fullstack/task/packages/client/src/App.tsx b/fullstack/task/packages/client/src/App.tsx
index f62d2a02..00c1726f 100644
--- a/fullstack/task/packages/client/src/App.tsx
+++ b/fullstack/task/packages/client/src/App.tsx
@@ -1,5 +1,49 @@
+import React from 'react';
+import { useQuery } from '@apollo/client';
+import { GET_EXCHANGE_RATES } from './graphql/queries';
+import { ExchangeRate } from './types/ExchangeRate';
+
+interface ExchangeRateResponse {
+ exchangeRatesList: ExchangeRate[];
+}
+
function App() {
- return
TODO
;
+ const { data, loading, error } = useQuery(GET_EXCHANGE_RATES);
+
+ if (loading) return Loading...
;
+ if (error) return Error: {error.message}
;
+
+ const exchangeRates = data?.exchangeRatesList || [];
+
+ return (
+
+
Exchange Rates
+
+
+
+ | Country |
+ Currency |
+ Amount |
+ Code |
+ Rate |
+ Last updated at |
+
+
+
+ {exchangeRates.map((rate) => (
+
+ | {rate.country} |
+ {rate.currency} |
+ {rate.amount} |
+ {rate.currencyCode} |
+ {rate.rate} |
+ {rate.updatedAtUtc} |
+
+ ))}
+
+
+
+ );
}
export default App;
diff --git a/fullstack/task/packages/client/src/graphql/queries.ts b/fullstack/task/packages/client/src/graphql/queries.ts
new file mode 100644
index 00000000..e5f50724
--- /dev/null
+++ b/fullstack/task/packages/client/src/graphql/queries.ts
@@ -0,0 +1,14 @@
+import { gql } from '@apollo/client';
+
+export const GET_EXCHANGE_RATES = gql`
+ query GetExchangeRates {
+ exchangeRatesList {
+ country
+ currency
+ currencyCode
+ amount
+ rate
+ updatedAtUtc
+ }
+ }
+`;
diff --git a/fullstack/task/packages/client/src/main.tsx b/fullstack/task/packages/client/src/main.tsx
index ef5f39c2..070c8ee1 100644
--- a/fullstack/task/packages/client/src/main.tsx
+++ b/fullstack/task/packages/client/src/main.tsx
@@ -4,8 +4,10 @@ import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client';
import App from './App';
const client = new ApolloClient({
- uri: 'http://localhost:4000/graphql',
- cache: new InMemoryCache(),
+ uri: 'http://localhost:4001/graphql',
+ cache: new InMemoryCache({
+ addTypename: false
+ }),
});
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
diff --git a/fullstack/task/packages/client/src/types/ExchangeRate.ts b/fullstack/task/packages/client/src/types/ExchangeRate.ts
new file mode 100644
index 00000000..21c1ed28
--- /dev/null
+++ b/fullstack/task/packages/client/src/types/ExchangeRate.ts
@@ -0,0 +1,8 @@
+export interface ExchangeRate {
+ country: string;
+ currency: string;
+ amount: number;
+ currencyCode: string;
+ rate: number;
+ updatedAtUtc?: string;
+}
diff --git a/fullstack/task/packages/server/project.json b/fullstack/task/packages/server/project.json
index 5dbf7487..253f6348 100644
--- a/fullstack/task/packages/server/project.json
+++ b/fullstack/task/packages/server/project.json
@@ -42,16 +42,16 @@
},
"configurations": {
"run": {
- "command": "yarn typeorm-ts-node-commonjs migration:run -d ./src/config/typeorm/data-source.ts"
+ "command": "yarn typeorm-ts-node-commonjs migration:run --dataSource ./src/config/typeorm/data-source.ts"
},
"revert": {
- "command": "yarn typeorm-ts-node-commonjs migration:revert -d ./src/config/typeorm/data-source.ts"
+ "command": "yarn typeorm-ts-node-commonjs migration:revert --dataSource ./src/config/typeorm/data-source.ts"
},
"generate": {
- "command": "yarn typeorm-ts-node-commonjs migration:generate -d ./src/config/typeorm/data-source.ts ./src/migrations/{args.name}"
+ "command": "yarn typeorm-ts-node-commonjs migration:generate --dataSource ./src/config/typeorm/data-source.ts ./src/migrations/{args.name}"
},
"create": {
- "command": "yarn typeorm-ts-node-commonjs migration:create -d ./src/config/typeorm/data-source.ts ./src/migrations/{args.name}"
+ "command": "yarn typeorm-ts-node-commonjs migration:create ./src/migrations/{args.name}"
}
}
}
diff --git a/fullstack/task/packages/server/schema.gql b/fullstack/task/packages/server/schema.gql
index 2453a887..8d898d21 100644
--- a/fullstack/task/packages/server/schema.gql
+++ b/fullstack/task/packages/server/schema.gql
@@ -17,8 +17,21 @@ A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date
"""
scalar DateTime
+type ExchangeRate {
+ id: ID!
+ createdAtUtc: DateTime!
+ updatedAtUtc: DateTime
+ deleteDateUtc: DateTime
+ version: Int!
+ country: String!
+ currency: String!
+ amount: Float!
+ currencyCode: String!
+ rate: Float!
+}
+
type Query {
- exchangeRates: String!
+ exchangeRatesList: [ExchangeRate!]!
exampleByName(name: String!): Example
}
diff --git a/fullstack/task/packages/server/src/app.module.ts b/fullstack/task/packages/server/src/app.module.ts
index 386fe012..f76f5506 100644
--- a/fullstack/task/packages/server/src/app.module.ts
+++ b/fullstack/task/packages/server/src/app.module.ts
@@ -5,6 +5,7 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { graphqlConfig, typeormConfig } from './config';
import { modules } from './entity-modules';
import { ExchangeRateModule } from './services/exchange-rate/exchange-rate.module';
+import { CurrencyFetchModule } from './services/currency-fetch/currency-fetch.module';
@Module({
imports: [
@@ -14,6 +15,7 @@ import { ExchangeRateModule } from './services/exchange-rate/exchange-rate.modul
TypeOrmModule.forRoot(typeormConfig),
GraphQLModule.forRoot(graphqlConfig),
ExchangeRateModule,
+ CurrencyFetchModule,
...modules,
],
controllers: [],
diff --git a/fullstack/task/packages/server/src/entities/cache-metadata.entity.ts b/fullstack/task/packages/server/src/entities/cache-metadata.entity.ts
new file mode 100644
index 00000000..6a7cd2fc
--- /dev/null
+++ b/fullstack/task/packages/server/src/entities/cache-metadata.entity.ts
@@ -0,0 +1,16 @@
+import { Field, ObjectType } from '@nestjs/graphql';
+import { IsString } from 'class-validator';
+import { Column, Entity, PrimaryColumn } from 'typeorm';
+
+@ObjectType()
+@Entity('cache_metadata')
+export class CacheMetadata {
+ @IsString()
+ @Field(() => String)
+ @PrimaryColumn({ type: 'varchar', length: 50 })
+ public cacheKey!: string;
+
+ @Field(() => Date)
+ @Column({ type: 'timestamptz' })
+ public lastFetchedAt!: Date;
+}
diff --git a/fullstack/task/packages/server/src/entities/exchange-rate.entity.ts b/fullstack/task/packages/server/src/entities/exchange-rate.entity.ts
new file mode 100644
index 00000000..c9e3842b
--- /dev/null
+++ b/fullstack/task/packages/server/src/entities/exchange-rate.entity.ts
@@ -0,0 +1,36 @@
+import { Field, Float, ObjectType } from '@nestjs/graphql';
+import { IsDecimal, IsString, Length } from 'class-validator';
+import { Column, Entity, Index } from 'typeorm';
+import { EntityWithMeta } from '../common';
+import { VAR_CHAR } from './constants';
+
+@ObjectType()
+@Entity('exchange_rates')
+@Index('IDX_exchange_rates_currency_code', ['currencyCode'], { unique: true })
+export class ExchangeRate extends EntityWithMeta {
+ @IsString()
+ @Field(() => String)
+ @Column({ ...VAR_CHAR })
+ public country!: string;
+
+ @IsString()
+ @Field(() => String)
+ @Column({ ...VAR_CHAR })
+ public currency!: string;
+
+ @IsDecimal()
+ @Field(() => Float)
+ @Column({ type: 'decimal', precision: 10, scale: 0 })
+ public amount!: number;
+
+ @IsString()
+ @Length(3, 3)
+ @Field(() => String)
+ @Column({ type: 'varchar', length: 3 })
+ public currencyCode!: string;
+
+ @IsDecimal()
+ @Field(() => Float)
+ @Column({ type: 'decimal', precision: 10, scale: 6 })
+ public rate!: number;
+}
diff --git a/fullstack/task/packages/server/src/entities/index.ts b/fullstack/task/packages/server/src/entities/index.ts
index 6b536a4a..7fe23f2a 100644
--- a/fullstack/task/packages/server/src/entities/index.ts
+++ b/fullstack/task/packages/server/src/entities/index.ts
@@ -1 +1,3 @@
export * from './example.entity';
+export * from './exchange-rate.entity';
+export * from './cache-metadata.entity';
diff --git a/fullstack/task/packages/server/src/main.ts b/fullstack/task/packages/server/src/main.ts
index f3750f7d..eed0779b 100644
--- a/fullstack/task/packages/server/src/main.ts
+++ b/fullstack/task/packages/server/src/main.ts
@@ -7,6 +7,7 @@ import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
+ app.enableCors();
app.useGlobalPipes(new ValidationPipe({ whitelist: false, transform: false }));
useContainer(app.select(AppModule), { fallbackOnErrors: true });
diff --git a/fullstack/task/packages/server/src/migrations/1758100643630-create-table-exchange_rates.ts b/fullstack/task/packages/server/src/migrations/1758100643630-create-table-exchange_rates.ts
new file mode 100644
index 00000000..733237d2
--- /dev/null
+++ b/fullstack/task/packages/server/src/migrations/1758100643630-create-table-exchange_rates.ts
@@ -0,0 +1,32 @@
+import { MigrationInterface, QueryRunner } from "typeorm"
+
+export class createTableExchangeRates1758100643630 implements MigrationInterface {
+
+ public async up(queryRunner: QueryRunner): Promise {
+ await queryRunner.query(`
+ CREATE TABLE "exchange_rates"
+ (
+ "id" uuid NOT NULL DEFAULT uuid_generate_v4(),
+ "createdAtUtc" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
+ "updatedAtUtc" TIMESTAMP WITH TIME ZONE DEFAULT now(),
+ "deleteDateUtc" TIMESTAMP WITH TIME ZONE,
+ "version" integer NOT NULL,
+ "country" character varying(255) NOT NULL,
+ "currency" character varying(255) NOT NULL,
+ "amount" numeric(10, 2) NOT NULL,
+ "currencyCode" character varying(255) NOT NULL,
+ "rate" numeric(10, 2) NOT NULL,
+ CONSTRAINT "PK_876duygd68as6d8a6d8as768" PRIMARY KEY ("id")
+ )`);
+
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_exchange_rates_currency_code" ON "exchange_rates" ("currencyCode")
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise {
+ await queryRunner.query(`DROP INDEX "IDX_exchange_rates_currency_code"`);
+ await queryRunner.query(`DROP TABLE "exchange_rates"`);
+ }
+
+}
diff --git a/fullstack/task/packages/server/src/migrations/1758102061344-create-cache-metadata-table.ts b/fullstack/task/packages/server/src/migrations/1758102061344-create-cache-metadata-table.ts
new file mode 100644
index 00000000..7c37d738
--- /dev/null
+++ b/fullstack/task/packages/server/src/migrations/1758102061344-create-cache-metadata-table.ts
@@ -0,0 +1,16 @@
+import { MigrationInterface, QueryRunner } from 'typeorm';
+
+export class CreateCacheMetadataTable1758102061344 implements MigrationInterface {
+ public async up(queryRunner: QueryRunner): Promise {
+ await queryRunner.query(`
+ CREATE TABLE cache_metadata (
+ "cacheKey" VARCHAR(50) PRIMARY KEY,
+ "lastFetchedAt" TIMESTAMPTZ NOT NULL
+ )
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise {
+ await queryRunner.query(`DROP TABLE IF EXISTS cache_metadata`);
+ }
+}
diff --git a/fullstack/task/packages/server/src/services/currency-fetch/currency-fetch.module.ts b/fullstack/task/packages/server/src/services/currency-fetch/currency-fetch.module.ts
new file mode 100644
index 00000000..20a60f6a
--- /dev/null
+++ b/fullstack/task/packages/server/src/services/currency-fetch/currency-fetch.module.ts
@@ -0,0 +1,11 @@
+import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { CurrencyFetchService } from './currency-fetch.service';
+import { ExchangeRate, CacheMetadata } from '../../entities';
+
+@Module({
+ imports: [TypeOrmModule.forFeature([ExchangeRate, CacheMetadata])],
+ providers: [CurrencyFetchService],
+ exports: [CurrencyFetchService],
+})
+export class CurrencyFetchModule {}
diff --git a/fullstack/task/packages/server/src/services/currency-fetch/currency-fetch.service.ts b/fullstack/task/packages/server/src/services/currency-fetch/currency-fetch.service.ts
new file mode 100644
index 00000000..8501c6d0
--- /dev/null
+++ b/fullstack/task/packages/server/src/services/currency-fetch/currency-fetch.service.ts
@@ -0,0 +1,160 @@
+import { Injectable, Logger } from '@nestjs/common';
+import { InjectRepository } from '@nestjs/typeorm';
+import { Repository, QueryRunner } from 'typeorm';
+import axios from 'axios';
+import { ExchangeRate, CacheMetadata } from '../../entities';
+
+interface CNBExchangeRateData {
+ country: string;
+ currency: string;
+ amount: number;
+ currencyCode: string;
+ rate: number;
+}
+
+@Injectable()
+export class CurrencyFetchService {
+ private readonly logger = new Logger(CurrencyFetchService.name);
+ private readonly CNB_URL = 'https://www.cnb.cz/en/financial-markets/foreign-exchange-market/central-bank-exchange-rate-fixing/central-bank-exchange-rate-fixing/daily.txt';
+ private readonly CACHE_KEY = 'exchange_rates';
+ private readonly CACHE_DURATION_MINUTES = 5;
+
+ constructor(
+ @InjectRepository(ExchangeRate)
+ private readonly exchangeRateRepository: Repository,
+ @InjectRepository(CacheMetadata)
+ private readonly cacheMetadataRepository: Repository,
+ ) {}
+
+ public async isCacheValid(): Promise {
+ try {
+ const cacheRecord = await this.cacheMetadataRepository.findOne({
+ where: { cacheKey: this.CACHE_KEY }
+ });
+
+ if (!cacheRecord) {
+ return false;
+ }
+
+ const cacheExpiry = new Date(cacheRecord.lastFetchedAt.getTime() + this.CACHE_DURATION_MINUTES * 60 * 1000);
+
+ return new Date() < cacheExpiry;
+ } catch (error) {
+ this.logger.error('Error checking cache validity', error);
+ return false;
+ }
+ }
+
+ public async getCachedExchangeRates(): Promise {
+ try {
+ const isCacheValid = await this.isCacheValid();
+ if (!isCacheValid) {
+ await this.fetchAndStoreExchangeRates();
+ }
+
+ const exchangeRates = await this.exchangeRateRepository.find({
+ order: { currencyCode: 'ASC' }
+ });
+
+ return exchangeRates;
+ } catch (error) {
+ this.logger.error('Error fetching cached exchange rates', error);
+ throw error;
+ }
+ }
+
+ public async fetchAndStoreExchangeRates(): Promise {
+ try {
+ const exchangeRates = await this.fetchFromCNB();
+ await this.storeExchangeRates(exchangeRates);
+ } catch (error) {
+ this.logger.error('Failed to fetch and store exchange rates', error);
+ throw error;
+ }
+ }
+
+ private async fetchFromCNB(): Promise {
+ try {
+ const response = await axios.get(this.CNB_URL);
+
+ if (response.status !== 200) {
+ throw new Error(`CNB API returned ${response.status}: ${response.statusText}`);
+ }
+
+ return this.parseCNBData(response.data);
+ } catch (error) {
+ this.logger.error('Error fetching from CNB API', error);
+ throw error;
+ }
+ }
+
+ private parseCNBData(textData: string): CNBExchangeRateData[] {
+ const lines = textData.trim().split('\n');
+ const dataLines = lines.slice(2);
+
+ const exchangeRates: CNBExchangeRateData[] = [];
+
+ for (const line of dataLines) {
+ if (line.trim()) {
+ const parts = line.split('|');
+
+ if (parts.length >= 5) {
+ exchangeRates.push({
+ country: parts[0].trim(),
+ currency: parts[1].trim(),
+ amount: parseInt(parts[2].trim()),
+ currencyCode: parts[3].trim(),
+ rate: parseFloat(parts[4].trim()),
+ });
+ }
+ }
+ }
+
+ return exchangeRates;
+ }
+
+ private async storeExchangeRates(exchangeRates: CNBExchangeRateData[]): Promise {
+ const queryRunner: QueryRunner = this.exchangeRateRepository.manager.connection.createQueryRunner();
+
+ await queryRunner.connect();
+ await queryRunner.startTransaction();
+
+ try {
+ const exchangeRateEntities = exchangeRates.map(rateData => ({
+ country: rateData.country,
+ currency: rateData.currency,
+ amount: rateData.amount,
+ currencyCode: rateData.currencyCode,
+ rate: rateData.rate,
+ }));
+
+ await queryRunner.manager
+ .createQueryBuilder()
+ .insert()
+ .into(ExchangeRate)
+ .values(exchangeRateEntities)
+ .orUpdate(['country', 'currency', 'amount', 'rate', 'updatedAtUtc'], ['currencyCode'])
+ .execute();
+
+
+ await queryRunner.manager
+ .createQueryBuilder()
+ .insert()
+ .into(CacheMetadata)
+ .values({
+ cacheKey: this.CACHE_KEY,
+ lastFetchedAt: new Date(),
+ })
+ .orUpdate(['lastFetchedAt'], ['cacheKey'])
+ .execute();
+
+ await queryRunner.commitTransaction();
+ } catch (error) {
+ await queryRunner.rollbackTransaction();
+ this.logger.error('Error storing exchange rates, transaction rolled back', error);
+ throw error;
+ } finally {
+ await queryRunner.release();
+ }
+ }
+}
diff --git a/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.module.ts b/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.module.ts
index d972c6e4..c19a0485 100644
--- a/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.module.ts
+++ b/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.module.ts
@@ -1,9 +1,12 @@
import { Module } from '@nestjs/common';
import { ExchangeRateService } from './exchange-rate.service';
import { ExchangeRateResolver } from './exchange-rate.resolver';
+import { CurrencyFetchModule } from '../currency-fetch/currency-fetch.module';
@Module({
- imports: [],
+ imports: [
+ CurrencyFetchModule,
+ ],
providers: [ExchangeRateService, ExchangeRateResolver],
exports: [ExchangeRateService],
})
diff --git a/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.resolver.ts b/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.resolver.ts
index 39087b66..8a8a6906 100644
--- a/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.resolver.ts
+++ b/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.resolver.ts
@@ -1,13 +1,13 @@
import { Query, Resolver } from '@nestjs/graphql';
import { ExchangeRateService } from './exchange-rate.service';
+import { ExchangeRate } from '../../entities';
@Resolver()
export class ExchangeRateResolver {
constructor(private readonly exchangeRateService: ExchangeRateService) {}
- // TODO: Implement a GraphQL Query that returns the exchange rates
- @Query(() => String)
- async exchangeRates(): Promise {
- return 'Hello';
+ @Query(() => [ExchangeRate])
+ async exchangeRatesList(): Promise {
+ return this.exchangeRateService.getExchangeRates();
}
}
diff --git a/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.service.ts b/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.service.ts
index d9ee80bb..33aaa376 100644
--- a/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.service.ts
+++ b/fullstack/task/packages/server/src/services/exchange-rate/exchange-rate.service.ts
@@ -1,11 +1,15 @@
-import { Injectable } from '@nestjs/common';
+import { Injectable, Logger } from '@nestjs/common';
+import { ExchangeRate, CacheMetadata } from '../../entities';
+import { CurrencyFetchService } from '../currency-fetch/currency-fetch.service';
@Injectable()
export class ExchangeRateService {
- public getExchangeRates = async () => {
- // TODO: Implement the fetching and parsing of the exchange rates.
- // Use this method in the resolver.
- return [];
- };
+ constructor(
+ private readonly currencyFetchService: CurrencyFetchService,
+ ) {}
+
+ public async getExchangeRates(): Promise {
+ return await this.currencyFetchService.getCachedExchangeRates();
+ }
}