From fd2b38617a238dfbf06b238aa6cdadad24f137c1 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Mon, 25 Nov 2024 19:10:53 +0500 Subject: [PATCH 1/7] feat(yield): return liquidity pools info --- .env.example | 7 ++ apps/api/src/app/data/poolInfo.ts | 33 +++++++ apps/api/src/app/plugins/env.ts | 17 ++++ apps/api/src/app/plugins/orm.ts | 31 +++++++ .../src/app/routes/__chainId/yield/const.ts | 4 + .../routes/__chainId/yield/getPoolsInfo.ts | 50 +++++++++++ .../src/app/routes/__chainId/yield/schemas.ts | 87 +++++++++++++++++++ .../src/app/routes/__chainId/yield/types.ts | 6 ++ apps/api/src/datasource.config.ts | 16 ++++ apps/twap/src/app/orderbook/order.ts | 2 +- apps/twap/src/app/orderbook/settlement.ts | 2 +- apps/twap/src/app/orderbook/trade.ts | 2 +- libs/shared/src/index.ts | 1 + .../utils => libs/shared/src}/transformers.ts | 0 tsconfig.base.json | 1 + 15 files changed, 256 insertions(+), 3 deletions(-) create mode 100644 apps/api/src/app/data/poolInfo.ts create mode 100644 apps/api/src/app/plugins/orm.ts create mode 100644 apps/api/src/app/routes/__chainId/yield/const.ts create mode 100644 apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts create mode 100644 apps/api/src/app/routes/__chainId/yield/schemas.ts create mode 100644 apps/api/src/app/routes/__chainId/yield/types.ts create mode 100644 apps/api/src/datasource.config.ts rename {apps/twap/src/app/utils => libs/shared/src}/transformers.ts (100%) diff --git a/.env.example b/.env.example index 11de6320..640423c7 100644 --- a/.env.example +++ b/.env.example @@ -45,6 +45,13 @@ #ORDERBOOK_DATABASE_USERNAME= #ORDERBOOK_DATABASE_PASSWORD= +# Analytics database (used in Yield aka Vampire attack) +#COW_ANALYTICS_DATABASE_NAME= +#COW_ANALYTICS_DATABASE_HOST= +#COW_ANALYTICS_DATABASE_PORT= +#COW_ANALYTICS_DATABASE_USERNAME= +#COW_ANALYTICS_DATABASE_PASSWORD= + # CMS #CMS_API_KEY= #CMS_BASE_URL=https://cms.cow.fi diff --git a/apps/api/src/app/data/poolInfo.ts b/apps/api/src/app/data/poolInfo.ts new file mode 100644 index 00000000..5f317b56 --- /dev/null +++ b/apps/api/src/app/data/poolInfo.ts @@ -0,0 +1,33 @@ +import { + Column, + Entity, + PrimaryColumn +} from 'typeorm'; +import { bufferToString, stringToBuffer } from '@cowprotocol/shared'; + +@Entity({ name: 'cow_amm_competitor_info', schema: 'public' }) +export class PoolInfo { + @PrimaryColumn('bytea', { + transformer: { from: bufferToString, to: stringToBuffer }, + }) + contract_address: string; + + // TODO + // @Column('int') + // chainId: number; + // + // @Column('varchar') + // provider: string; + + @Column('double precision') + apr: number; + + @Column('double precision') + fee: number; + + @Column('double precision') + tvl: number; + + @Column('double precision') + volume: number; +} diff --git a/apps/api/src/app/plugins/env.ts b/apps/api/src/app/plugins/env.ts index 1afb8b27..8ada4c91 100644 --- a/apps/api/src/app/plugins/env.ts +++ b/apps/api/src/app/plugins/env.ts @@ -41,6 +41,23 @@ const schema = { MORALIS_API_KEY: { type: 'string', }, + + // CoW Analytics DB + COW_ANALYTICS_DATABASE_NAME: { + type: 'string', + }, + COW_ANALYTICS_DATABASE_HOST: { + type: 'string', + }, + COW_ANALYTICS_DATABASE_PORT: { + type: 'number', + }, + COW_ANALYTICS_DATABASE_USERNAME: { + type: 'string', + }, + COW_ANALYTICS_DATABASE_PASSWORD: { + type: 'string', + }, }, }; diff --git a/apps/api/src/app/plugins/orm.ts b/apps/api/src/app/plugins/orm.ts new file mode 100644 index 00000000..ac17d127 --- /dev/null +++ b/apps/api/src/app/plugins/orm.ts @@ -0,0 +1,31 @@ +import 'reflect-metadata'; +import { FastifyInstance } from 'fastify'; +import typeORMPlugin from 'typeorm-fastify-plugin'; +import fp from 'fastify-plugin'; +import { PoolInfo } from '../data/poolInfo'; + +export default fp(async function (fastify: FastifyInstance) { + fastify.register(typeORMPlugin, { + host: fastify.config.COW_ANALYTICS_DATABASE_HOST, + port: Number(fastify.config.COW_ANALYTICS_DATABASE_PORT), + type: 'postgres', + database: fastify.config.COW_ANALYTICS_DATABASE_NAME, + username: fastify.config.COW_ANALYTICS_DATABASE_USERNAME, + password: fastify.config.COW_ANALYTICS_DATABASE_PASSWORD, + entities: [PoolInfo], + ssl: true, + extra: { + ssl: { + rejectUnauthorized: false + } + } + }); + + fastify.ready((err) => { + if (err) { + throw err; + } + + fastify.orm.runMigrations({ transaction: 'all' }); + }); +}); diff --git a/apps/api/src/app/routes/__chainId/yield/const.ts b/apps/api/src/app/routes/__chainId/yield/const.ts new file mode 100644 index 00000000..37ad1b4a --- /dev/null +++ b/apps/api/src/app/routes/__chainId/yield/const.ts @@ -0,0 +1,4 @@ +import ms from 'ms'; + +export const POOLS_RESULT_LIMIT = 500 +export const POOLS_QUERY_CACHE = ms('12h') \ No newline at end of file diff --git a/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts b/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts new file mode 100644 index 00000000..b30bfb8d --- /dev/null +++ b/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts @@ -0,0 +1,50 @@ +import { FastifyPluginAsync } from 'fastify'; +import { FromSchema } from 'json-schema-to-ts'; +import { PoolInfo } from '../../../data/poolInfo'; +import { In } from 'typeorm'; +import { poolsInfoBodySchema, errorSchema, paramsSchema, poolsInfoSuccessSchema } from './schemas'; +import { POOLS_QUERY_CACHE, POOLS_RESULT_LIMIT } from './const'; + +type RouteSchema = FromSchema; +type SuccessSchema = FromSchema; +type ErrorSchema = FromSchema; +type BodySchema = FromSchema; + +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.post<{ + Params: RouteSchema; + Reply: SuccessSchema | ErrorSchema; + Body: BodySchema; + }>( + '/getPoolsInfo', + { + schema: { + params: paramsSchema, + response: { + '2XX': poolsInfoSuccessSchema, + '400': errorSchema, + }, + body: poolsInfoBodySchema + }, + }, + async function (request, reply) { + const { chainId } = request.params; + const poolsAddresses = request.body; + + const poolInfoRepository = fastify.orm.getRepository(PoolInfo); + + const results = await poolInfoRepository.find({ + take: POOLS_RESULT_LIMIT, + where: { + contract_address: In(poolsAddresses), + // TODO chainId + }, + cache: POOLS_QUERY_CACHE + }) + + reply.status(200).send(results); + } + ); +}; + +export default root; diff --git a/apps/api/src/app/routes/__chainId/yield/schemas.ts b/apps/api/src/app/routes/__chainId/yield/schemas.ts new file mode 100644 index 00000000..91d0bc4c --- /dev/null +++ b/apps/api/src/app/routes/__chainId/yield/schemas.ts @@ -0,0 +1,87 @@ +import { AddressSchema, ChainIdSchema } from '../../../schemas'; +import { JSONSchema } from 'json-schema-to-ts'; +import { POOLS_RESULT_LIMIT } from './const'; + +export const paramsSchema = { + type: 'object', + required: ['chainId'], + additionalProperties: false, + properties: { + chainId: ChainIdSchema, + }, +} as const satisfies JSONSchema; + +export const poolsInfoSuccessSchema = { + type: 'array', + items: { + type: 'object', + required: [ + 'contract_address', + // TODO + // 'chainId', + // 'provider', + 'apr', + 'fee', + 'tvl', + 'volume' + ], + additionalProperties: false, + properties: { + contract_address: { + title: 'Pool address', + type: 'string', + pattern: AddressSchema.pattern + }, + // chainId: ChainIdSchema, + // provider: { + // title: 'Liquidity provider', + // type: 'string', + // }, + apr: { + title: 'APR', + description: 'Annual Percentage Rate', + type: 'number', + }, + fee: { + title: 'Fee tier', + description: 'Pool fee percent', + type: 'number', + }, + tvl: { + title: 'TVL', + description: 'Total value locked (in USD)', + type: 'number', + }, + volume: { + title: 'Volume 24h', + description: 'Trading volume in the last 24 hours (in USD)', + type: 'number', + }, + }, + }, +} as const satisfies JSONSchema; + +export const poolsInfoBodySchema = { + type: 'array', + items: { + title: 'Pool address', + description: 'Blockchain address of the pool', + type: 'string', + pattern: AddressSchema.pattern, + }, + minItems: 1, + maxItems: POOLS_RESULT_LIMIT +} as const satisfies JSONSchema; + +export const errorSchema = { + type: 'object', + required: ['message'], + additionalProperties: false, + properties: { + message: { + title: 'Message', + description: 'Message describing the error.', + type: 'string', + }, + }, +} as const satisfies JSONSchema; \ No newline at end of file diff --git a/apps/api/src/app/routes/__chainId/yield/types.ts b/apps/api/src/app/routes/__chainId/yield/types.ts new file mode 100644 index 00000000..4e22d63f --- /dev/null +++ b/apps/api/src/app/routes/__chainId/yield/types.ts @@ -0,0 +1,6 @@ +export interface PoolInfo { + apy: number + tvl: number + feeTier: number + volume24h: number +} \ No newline at end of file diff --git a/apps/api/src/datasource.config.ts b/apps/api/src/datasource.config.ts new file mode 100644 index 00000000..4d38ba6a --- /dev/null +++ b/apps/api/src/datasource.config.ts @@ -0,0 +1,16 @@ +import * as dotenv from 'dotenv'; +import { DataSource } from 'typeorm'; + +dotenv.config(); + +export const cowAnalyticsDb = new DataSource({ + type: 'postgres', + host: process.env.COW_ANALYTICS_DATABASE_HOST, + port: Number(process.env.COW_ANALYTICS_DATABASE_PORT), + username: process.env.COW_ANALYTICS_DATABASE_USERNAME, + password: process.env.COW_ANALYTICS_DATABASE_PASSWORD, + database: process.env.COW_ANALYTICS_DATABASE_NAME, + entities: ['src/app/data/*.ts'], +}); + +cowAnalyticsDb.initialize(); diff --git a/apps/twap/src/app/orderbook/order.ts b/apps/twap/src/app/orderbook/order.ts index cac561d4..6fb6cf7f 100644 --- a/apps/twap/src/app/orderbook/order.ts +++ b/apps/twap/src/app/orderbook/order.ts @@ -4,7 +4,7 @@ import { bufferToString, stringToBigInt, stringToBuffer, -} from '../utils/transformers'; +} from '@cowprotocol/shared'; @Entity({ name: 'orders' }) export class Order { diff --git a/apps/twap/src/app/orderbook/settlement.ts b/apps/twap/src/app/orderbook/settlement.ts index cc7d2c9b..f2d117ff 100644 --- a/apps/twap/src/app/orderbook/settlement.ts +++ b/apps/twap/src/app/orderbook/settlement.ts @@ -4,7 +4,7 @@ import { bufferToString, stringToBigInt, stringToBuffer, -} from '../utils/transformers'; +} from '@cowprotocol/shared'; @Entity({ name: 'settlements' }) export class Settlement { diff --git a/apps/twap/src/app/orderbook/trade.ts b/apps/twap/src/app/orderbook/trade.ts index 25f7e344..849b8c30 100644 --- a/apps/twap/src/app/orderbook/trade.ts +++ b/apps/twap/src/app/orderbook/trade.ts @@ -4,7 +4,7 @@ import { bufferToString, stringToBigInt, stringToBuffer, -} from '../utils/transformers'; +} from '@cowprotocol/shared'; @Entity({ name: 'trades' }) export class Trade { diff --git a/libs/shared/src/index.ts b/libs/shared/src/index.ts index 7918be87..76a41556 100644 --- a/libs/shared/src/index.ts +++ b/libs/shared/src/index.ts @@ -1,3 +1,4 @@ export * from './types'; export * from './const'; export * from './utils'; +export * from './transformers'; diff --git a/apps/twap/src/app/utils/transformers.ts b/libs/shared/src/transformers.ts similarity index 100% rename from apps/twap/src/app/utils/transformers.ts rename to libs/shared/src/transformers.ts diff --git a/tsconfig.base.json b/tsconfig.base.json index 0020d49b..0aa668c8 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -20,6 +20,7 @@ "strict": true, "strictNullChecks": true, "alwaysStrict": true, + "strictPropertyInitialization": false, "paths": { "@cowprotocol/abis": ["libs/abis/src/index.ts"], "@cowprotocol/cms-api": ["libs/cms-api/src/index.ts"], From 052f742d15ce59dcc673a149b7f0dabcac3c7247 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 28 Nov 2024 15:56:30 +0500 Subject: [PATCH 2/7] chore: add chainId and project --- apps/api/src/app/data/poolInfo.ts | 11 +++++------ .../app/routes/__chainId/yield/getPoolsInfo.ts | 2 +- .../api/src/app/routes/__chainId/yield/schemas.ts | 15 +++++++-------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/apps/api/src/app/data/poolInfo.ts b/apps/api/src/app/data/poolInfo.ts index 5f317b56..d5860b21 100644 --- a/apps/api/src/app/data/poolInfo.ts +++ b/apps/api/src/app/data/poolInfo.ts @@ -12,12 +12,11 @@ export class PoolInfo { }) contract_address: string; - // TODO - // @Column('int') - // chainId: number; - // - // @Column('varchar') - // provider: string; + @Column('int') + chain_id: number; + + @Column('varchar') + project: string; @Column('double precision') apr: number; diff --git a/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts b/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts index b30bfb8d..d37936aa 100644 --- a/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts +++ b/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts @@ -37,7 +37,7 @@ const root: FastifyPluginAsync = async (fastify): Promise => { take: POOLS_RESULT_LIMIT, where: { contract_address: In(poolsAddresses), - // TODO chainId + chain_id: chainId }, cache: POOLS_QUERY_CACHE }) diff --git a/apps/api/src/app/routes/__chainId/yield/schemas.ts b/apps/api/src/app/routes/__chainId/yield/schemas.ts index 91d0bc4c..6f1faf1a 100644 --- a/apps/api/src/app/routes/__chainId/yield/schemas.ts +++ b/apps/api/src/app/routes/__chainId/yield/schemas.ts @@ -17,9 +17,8 @@ export const poolsInfoSuccessSchema = { type: 'object', required: [ 'contract_address', - // TODO - // 'chainId', - // 'provider', + 'chain_id', + 'project', 'apr', 'fee', 'tvl', @@ -32,11 +31,11 @@ export const poolsInfoSuccessSchema = { type: 'string', pattern: AddressSchema.pattern }, - // chainId: ChainIdSchema, - // provider: { - // title: 'Liquidity provider', - // type: 'string', - // }, + chain_id: ChainIdSchema, + project: { + title: 'Liquidity provider', + type: 'string', + }, apr: { title: 'APR', description: 'Annual Percentage Rate', From 83b293abe384aa8d134f6ccb1f5ce1be0a5ad1ca Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 28 Nov 2024 16:23:22 +0500 Subject: [PATCH 3/7] feat: add getPoolsAverageApr method --- .../__chainId/yield/getPoolsAverageApr.ts | 61 +++++++++++++++++++ .../routes/__chainId/yield/getPoolsInfo.ts | 10 ++- .../src/app/routes/__chainId/yield/schemas.ts | 7 +++ .../src/app/routes/__chainId/yield/utils.ts | 11 ++++ 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 apps/api/src/app/routes/__chainId/yield/getPoolsAverageApr.ts create mode 100644 apps/api/src/app/routes/__chainId/yield/utils.ts diff --git a/apps/api/src/app/routes/__chainId/yield/getPoolsAverageApr.ts b/apps/api/src/app/routes/__chainId/yield/getPoolsAverageApr.ts new file mode 100644 index 00000000..64f52697 --- /dev/null +++ b/apps/api/src/app/routes/__chainId/yield/getPoolsAverageApr.ts @@ -0,0 +1,61 @@ +import { FastifyPluginAsync } from 'fastify'; +import { FromSchema } from 'json-schema-to-ts'; +import { PoolInfo } from '../../../data/poolInfo'; +import { + errorSchema, + paramsSchema, + poolsAverageAprBodySchema +} from './schemas'; +import { trimDoubleQuotes } from './utils'; + +type RouteSchema = FromSchema; +type SuccessSchema = FromSchema; +type ErrorSchema = FromSchema; + +interface PoolInfoResult { + project: string; + average_apr: number; +} + +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.get<{ + Params: RouteSchema; + Reply: SuccessSchema | ErrorSchema; + }>( + '/getPoolsAverageApr', + { + schema: { + params: paramsSchema, + response: { + '2XX': poolsAverageAprBodySchema, + '400': errorSchema, + }, + }, + }, + async function (request, reply) { + const { chainId } = request.params; + + const poolInfoRepository = fastify.orm.getRepository(PoolInfo); + + const result = await poolInfoRepository.query(` + SELECT project, + AVG(apr) AS average_apr + FROM cow_amm_competitor_info + WHERE chain_id = ${chainId} + GROUP BY project; + `) + + const averageApr = result.reduce((acc: Record, val: PoolInfoResult) => { + const projectName = trimDoubleQuotes(val.project) + + acc[projectName] = +val.average_apr.toFixed(6) + + return acc + }, {}) + + reply.status(200).send(averageApr); + } + ); +}; + +export default root; diff --git a/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts b/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts index d37936aa..fe3e8661 100644 --- a/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts +++ b/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts @@ -4,6 +4,7 @@ import { PoolInfo } from '../../../data/poolInfo'; import { In } from 'typeorm'; import { poolsInfoBodySchema, errorSchema, paramsSchema, poolsInfoSuccessSchema } from './schemas'; import { POOLS_QUERY_CACHE, POOLS_RESULT_LIMIT } from './const'; +import { trimDoubleQuotes } from './utils'; type RouteSchema = FromSchema; type SuccessSchema = FromSchema; @@ -42,7 +43,14 @@ const root: FastifyPluginAsync = async (fastify): Promise => { cache: POOLS_QUERY_CACHE }) - reply.status(200).send(results); + const mappedResults = results.map(res => { + return { + ...res, + project: trimDoubleQuotes(res.project) + } + }) + + reply.status(200).send(mappedResults); } ); }; diff --git a/apps/api/src/app/routes/__chainId/yield/schemas.ts b/apps/api/src/app/routes/__chainId/yield/schemas.ts index 6f1faf1a..e2456d20 100644 --- a/apps/api/src/app/routes/__chainId/yield/schemas.ts +++ b/apps/api/src/app/routes/__chainId/yield/schemas.ts @@ -72,6 +72,13 @@ export const poolsInfoBodySchema = { maxItems: POOLS_RESULT_LIMIT } as const satisfies JSONSchema; +export const poolsAverageAprBodySchema = { + type: 'object', + title: 'Liquidity provider - apr', + additionalProperties: true +} as const satisfies JSONSchema; + + export const errorSchema = { type: 'object', required: ['message'], diff --git a/apps/api/src/app/routes/__chainId/yield/utils.ts b/apps/api/src/app/routes/__chainId/yield/utils.ts new file mode 100644 index 00000000..7b039229 --- /dev/null +++ b/apps/api/src/app/routes/__chainId/yield/utils.ts @@ -0,0 +1,11 @@ +export function trimDoubleQuotes(value: string): string { + if (value[0] === '"') { + return trimDoubleQuotes(value.slice(1)) + } + + if (value[value.length - 1] === '"') { + return trimDoubleQuotes(value.slice(0, -1)) + } + + return value +} \ No newline at end of file From aa6b762bcdde5571a84ab7fbf02a8cc17e5169a8 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 28 Nov 2024 16:52:59 +0500 Subject: [PATCH 4/7] chore: fix pools info request --- apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts | 2 +- apps/api/src/app/routes/__chainId/yield/schemas.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts b/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts index fe3e8661..a399ac1a 100644 --- a/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts +++ b/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts @@ -37,7 +37,7 @@ const root: FastifyPluginAsync = async (fastify): Promise => { const results = await poolInfoRepository.find({ take: POOLS_RESULT_LIMIT, where: { - contract_address: In(poolsAddresses), + ...(poolsAddresses.length > 0 ? { contract_address: In(poolsAddresses) } : null), chain_id: chainId }, cache: POOLS_QUERY_CACHE diff --git a/apps/api/src/app/routes/__chainId/yield/schemas.ts b/apps/api/src/app/routes/__chainId/yield/schemas.ts index e2456d20..cd6291e7 100644 --- a/apps/api/src/app/routes/__chainId/yield/schemas.ts +++ b/apps/api/src/app/routes/__chainId/yield/schemas.ts @@ -68,7 +68,6 @@ export const poolsInfoBodySchema = { type: 'string', pattern: AddressSchema.pattern, }, - minItems: 1, maxItems: POOLS_RESULT_LIMIT } as const satisfies JSONSchema; From 99ebb0eb4eef66ce10b39d3dae80b30955c9dae0 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 29 Nov 2024 11:40:21 +0500 Subject: [PATCH 5/7] chore: rename yield methods --- .../src/app/routes/__chainId/yield/getPoolsAverageApr.ts | 6 +++++- apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/api/src/app/routes/__chainId/yield/getPoolsAverageApr.ts b/apps/api/src/app/routes/__chainId/yield/getPoolsAverageApr.ts index 64f52697..046a3796 100644 --- a/apps/api/src/app/routes/__chainId/yield/getPoolsAverageApr.ts +++ b/apps/api/src/app/routes/__chainId/yield/getPoolsAverageApr.ts @@ -7,6 +7,7 @@ import { poolsAverageAprBodySchema } from './schemas'; import { trimDoubleQuotes } from './utils'; +import { CACHE_CONTROL_HEADER, getCacheControlHeaderValue } from '../../../../utils/cache'; type RouteSchema = FromSchema; type SuccessSchema = FromSchema; @@ -17,12 +18,14 @@ interface PoolInfoResult { average_apr: number; } +const CACHE_SECONDS = 21600; // 6 hours + const root: FastifyPluginAsync = async (fastify): Promise => { fastify.get<{ Params: RouteSchema; Reply: SuccessSchema | ErrorSchema; }>( - '/getPoolsAverageApr', + '/pools-average-apr', { schema: { params: paramsSchema, @@ -53,6 +56,7 @@ const root: FastifyPluginAsync = async (fastify): Promise => { return acc }, {}) + reply.header(CACHE_CONTROL_HEADER, getCacheControlHeaderValue(CACHE_SECONDS)); reply.status(200).send(averageApr); } ); diff --git a/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts b/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts index a399ac1a..67982163 100644 --- a/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts +++ b/apps/api/src/app/routes/__chainId/yield/getPoolsInfo.ts @@ -17,7 +17,7 @@ const root: FastifyPluginAsync = async (fastify): Promise => { Reply: SuccessSchema | ErrorSchema; Body: BodySchema; }>( - '/getPoolsInfo', + '/pools', { schema: { params: paramsSchema, From 7e86f4ae5ad07d97628efbdc79aef898430b6d74 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 3 Dec 2024 14:05:27 +0500 Subject: [PATCH 6/7] chore: fix ts config --- apps/api/tsconfig.app.json | 2 +- apps/api/tsconfig.json | 1 + tsconfig.base.json | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/api/tsconfig.app.json b/apps/api/tsconfig.app.json index f5e2e085..1314ca3b 100644 --- a/apps/api/tsconfig.app.json +++ b/apps/api/tsconfig.app.json @@ -3,7 +3,7 @@ "compilerOptions": { "outDir": "../../dist/out-tsc", "module": "commonjs", - "types": ["node"] + "types": ["node"], }, "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"], "include": ["src/**/*.ts"] diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json index c1e2dd4e..bf773b83 100644 --- a/apps/api/tsconfig.json +++ b/apps/api/tsconfig.json @@ -11,6 +11,7 @@ } ], "compilerOptions": { + "strictPropertyInitialization": false, "esModuleInterop": true } } diff --git a/tsconfig.base.json b/tsconfig.base.json index 0aa668c8..0020d49b 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -20,7 +20,6 @@ "strict": true, "strictNullChecks": true, "alwaysStrict": true, - "strictPropertyInitialization": false, "paths": { "@cowprotocol/abis": ["libs/abis/src/index.ts"], "@cowprotocol/cms-api": ["libs/cms-api/src/index.ts"], From 503e839939388e6c3d30737dfd2c935ff25858a2 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 3 Dec 2024 14:21:04 +0500 Subject: [PATCH 7/7] chore: do not fail when cow analytics db vars are not set --- apps/api/src/app/plugins/orm.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/api/src/app/plugins/orm.ts b/apps/api/src/app/plugins/orm.ts index ac17d127..dce974b5 100644 --- a/apps/api/src/app/plugins/orm.ts +++ b/apps/api/src/app/plugins/orm.ts @@ -5,13 +5,24 @@ import fp from 'fastify-plugin'; import { PoolInfo } from '../data/poolInfo'; export default fp(async function (fastify: FastifyInstance) { - fastify.register(typeORMPlugin, { + const dbParams = { host: fastify.config.COW_ANALYTICS_DATABASE_HOST, port: Number(fastify.config.COW_ANALYTICS_DATABASE_PORT), - type: 'postgres', database: fastify.config.COW_ANALYTICS_DATABASE_NAME, username: fastify.config.COW_ANALYTICS_DATABASE_USERNAME, password: fastify.config.COW_ANALYTICS_DATABASE_PASSWORD, + } + + const dbParamsAreInvalid = Object.values(dbParams).some((v) => Number.isNaN(v) || v === undefined); + + if (dbParamsAreInvalid) { + console.error('Invalid CoW Analytics database parameters, please check COW_ANALYTICS_* env vars'); + return + } + + fastify.register(typeORMPlugin, { + ...dbParams, + type: 'postgres', entities: [PoolInfo], ssl: true, extra: {