diff --git a/.env.example b/.env.example index 05b63787..9d1e09a9 100644 --- a/.env.example +++ b/.env.example @@ -90,4 +90,7 @@ # ETHPLORER_API_KEY= # MORALIS -# MORALIS_API_KEY= \ No newline at end of file +# MORALIS_API_KEY= + +# Alchemy API +# ALCHEMY_API_KEY= \ No newline at end of file diff --git a/apps/api/src/app/routes/__chainId/gas/gasPrice.ts b/apps/api/src/app/routes/__chainId/gas/gasPrice.ts new file mode 100644 index 00000000..99356cd4 --- /dev/null +++ b/apps/api/src/app/routes/__chainId/gas/gasPrice.ts @@ -0,0 +1,186 @@ +import { FastifyPluginAsync } from 'fastify'; +import { server } from '../../../../main'; +import { + CACHE_CONTROL_HEADER, + getCacheControlHeaderValue, +} from '../../../../utils/cache'; +import ms from 'ms'; +import { ValuePoint } from '../orders/types'; + +const CACHE_SECONDS = ms('10m') / 1000; + +// Prometheus configuration +const PROMETHEUS_URL = process.env.PROMETHEUS_URL; +const PROMETHEUS_USERNAME = process.env.PROMETHEUS_USERNAME; +const PROMETHEUS_PASSWORD = process.env.PROMETHEUS_PASSWORD; +const GAS_PRICE_QUERY = 'gp_v2_api_gas_price{network="mainnet"}'; +const DEFAULT_STEP = '5m'; // Default step interval +const DEFAULT_RANGE = '24h'; // Default time range + +interface GasPriceDataPoint { + time: number; + value: string; +} + +interface GasPriceResponse { + data: GasPriceDataPoint[]; +} + +interface PrometheusResponse { + status: string; + data: { + resultType: string; + result: Array<{ + metric: Record; + values: Array<[number, string]>; + }>; + }; +} + +/** + * Fetches gas price data from Prometheus using query_range + */ +export async function fetchGasPriceFromPrometheus( + range: string = DEFAULT_RANGE, + step: string = DEFAULT_STEP +): Promise { + try { + const query = encodeURIComponent(GAS_PRICE_QUERY); + const url = `${PROMETHEUS_URL}/api/v1/query_range?query=${query}&start=${getStartTime( + range + )}&end=${Math.floor(Date.now() / 1000)}&step=${step}`; + + server.log.debug(`Fetching gas price from Prometheus: ${url}`); + + // Prepare fetch options with authentication if credentials are provided + const fetchOptions: RequestInit = {}; + + if (PROMETHEUS_USERNAME && PROMETHEUS_PASSWORD) { + const authHeader = + 'Basic ' + + Buffer.from(`${PROMETHEUS_USERNAME}:${PROMETHEUS_PASSWORD}`).toString( + 'base64' + ); + fetchOptions.headers = { + Authorization: authHeader, + }; + } + + const response = await fetch(url, fetchOptions); + + if (!response.ok) { + server.log.error( + `Failed to fetch gas price from Prometheus: ${response.statusText}` + ); + return undefined; + } + + const data = (await response.json()) as PrometheusResponse; + + if (data.status !== 'success' || !data.data.result.length) { + return undefined; + } + + const results = data.data.result; + const values = results.flatMap((result) => result.values); + + if (!values || values.length === 0) { + return undefined; + } + + // Format data points + const dataPoints = values.map(([timestamp, value]) => ({ + time: Math.floor(timestamp) * 1000, + value, + })); + + return dataPoints; + } catch (error) { + server.log.error( + `Error fetching gas price from Prometheus: ${ + error instanceof Error ? error.message : 'Unknown error' + }` + ); + return undefined; + } +} + +/** + * Calculate the start time based on the range + */ +function getStartTime(range: string): number { + const now = Math.floor(Date.now() / 1000); + const rangeMs = ms(range); + return now - Math.floor(rangeMs / 1000); +} + +const gasPrice: FastifyPluginAsync = async (fastify): Promise => { + fastify.get<{ + Reply: GasPriceResponse; + Querystring: { + range?: string; + step?: string; + }; + }>( + '/gasPrice', + { + schema: { + description: 'Get the gas price for a given chain', + tags: ['gas'], + querystring: { + type: 'object', + properties: { + range: { + type: 'string', + description: 'Time range to fetch data for (e.g. 1h, 24h, 7d)', + default: DEFAULT_RANGE, + }, + step: { + type: 'string', + description: 'Step interval (e.g. 1m, 5m, 1h)', + default: DEFAULT_STEP, + }, + }, + }, + response: { + 200: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + time: { type: 'number' }, + value: { type: 'string' }, + }, + }, + }, + }, + }, + }, + }, + }, + async function (request, reply) { + reply.header( + CACHE_CONTROL_HEADER, + getCacheControlHeaderValue(CACHE_SECONDS) + ); + + const { range, step } = request.query; + + // Fetch gas price data from Prometheus + const gasPriceData = await fetchGasPriceFromPrometheus(range, step); + + if (!gasPriceData) { + return reply.send({ data: [] }); + } + + return reply.send({ + data: gasPriceData, + }); + } + ); +}; + +export default gasPrice; diff --git a/apps/api/src/app/routes/__chainId/orders/__oderId/estimatedFillPrice.ts b/apps/api/src/app/routes/__chainId/orders/__oderId/estimatedFillPrice.ts new file mode 100644 index 00000000..0df12f84 --- /dev/null +++ b/apps/api/src/app/routes/__chainId/orders/__oderId/estimatedFillPrice.ts @@ -0,0 +1,210 @@ +import { SlippageService, slippageServiceSymbol } from '@cowprotocol/services'; + +import { ChainIdSchema, OrderIdSchema } from '../../../../schemas'; +import { FastifyPluginAsync } from 'fastify'; +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; +import { apiContainer } from '../../../../inversify.config'; +import { + CACHE_CONTROL_HEADER, + getCacheControlHeaderValue, +} from '../../../../../utils/cache'; +import { OrderBookApi } from '@cowprotocol/cow-sdk'; +import { fetchTokenHistory } from '../../../../../utils/alchemy'; +import { get24HourRange, getLast24HourRange } from '../../../../../utils/date'; +import { Big, RoundingMode } from 'bigdecimal.js'; +import { getEstimatedFillPrices } from '../getEstimatedFillPrices'; +import { ValuePoint } from '../types'; +import { fetchGasPriceFromPrometheus } from '../../gas/gasPrice'; +import { + Erc20Repository, + erc20RepositorySymbol, +} from '@cowprotocol/repositories'; + +const CACHE_SECONDS = 120; +const ETH_DECIMALS = 18; + +const routeSchema = { + type: 'object', + required: ['chainId'], + additionalProperties: false, + properties: { + chainId: ChainIdSchema, + }, +} as const satisfies JSONSchema; + +const gasCostQueryStringSchema = { + type: 'object', + properties: { + orderId: OrderIdSchema, + }, +} as const satisfies JSONSchema; + +const gasCostSuccessSchema = { + type: 'array', + items: { + type: 'object', + required: ['time', 'fillPrice', 'gasPriceGwei', 'sellTokenPriceInEthWei'], + additionalProperties: false, + properties: { + time: { + type: 'number', + description: 'Unix timestamp in seconds', + }, + fillPrice: { + type: 'string', + description: 'Gas cost expressed in sell token decimals', + }, + gasPriceGwei: { + type: 'string', + description: 'Gas price in Gwei', + }, + sellTokenPriceInEthWei: { + type: 'string', + description: 'Sell token price in ETH Wei', + }, + }, + }, +} as const satisfies JSONSchema; + +type RouteSchema = FromSchema; + +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.get<{ + Params: RouteSchema; + Querystring: FromSchema; + Reply: FromSchema; + }>( + '/estimatedFillPrice', + { + schema: { + description: 'Retrieve 24h gas cost time series in 5-minute intervals', + tags: ['orders'], + params: routeSchema, + querystring: gasCostQueryStringSchema, + response: { + '2XX': gasCostSuccessSchema, + }, + }, + }, + async function (request, reply) { + const { chainId } = request.params; + const orderId = request.query.orderId as string; + fastify.log.info( + `Get gas cost time series for chain ${chainId} in sell token` + ); + + // TODO: Implement the actual gas cost fetching logic + + // Get order details from orderbook + const orderBookApi = new OrderBookApi({ chainId, env: 'prod' }); + const order = await orderBookApi.getOrder(orderId as string); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const gasAmountString = (order as any).quote?.gasAmount as + | string + | undefined; + + if (!gasAmountString) { + throw new Error( + 'Gas amount not found. Required for estimated fill price calculation.' + ); + } + + // Get gas prices from prometheus + + // Get Ethereum prices in USD (coingecko) + const authToken = process.env.ALCHEMY_API_KEY as string; + const { start, end } = getLast24HourRange(); + const startTime = new Date(start * 1000); + const endTime = new Date(end * 1000); + const weth_address = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'; + const ethPriceUsd = await await fetchTokenHistory( + weth_address, + startTime, + endTime, + authToken, + chainId + ); + + // Get Token prices in USD + const sellTokenUsd = await await fetchTokenHistory( + order.sellToken, + startTime, + endTime, + authToken, + chainId + ); + + const sellTokenPriceInEth: ValuePoint[] = []; + if (ethPriceUsd && sellTokenUsd) { + // TODO: use a wiser approach here + const length = Math.min(sellTokenUsd.length, ethPriceUsd.length); + for (let i = 0; i < length; i++) { + const sellTokenPrice = new Big(sellTokenUsd[i].value.toString()); + const ethPrice = new Big(ethPriceUsd[i].value.toString()); + const value = sellTokenPrice.divide( + ethPrice, + 20, + RoundingMode.HALF_UP + ); + sellTokenPriceInEth.push({ + value: value.toString(), + time: new Date(sellTokenUsd[i].timestamp).getTime(), + }); + } + } + + const erc20Repository: Erc20Repository = apiContainer.get( + erc20RepositorySymbol + ); + + const sellToken = await erc20Repository.get(chainId, order.sellToken); + // const buyToken = await erc20Repository.get(chainId, order.buyToken); + + const sellTokenDecimals = sellToken?.decimals || 18; + // const buyTokenDecimals = buyToken?.decimals || 18; + const tokenDecimalDifference = sellTokenDecimals - ETH_DECIMALS; + + const sellTokenPriceInWei = sellTokenPriceInEth.map(({ time, value }) => { + const newValue = new Big(value) + .divide(10 ** tokenDecimalDifference) + .toString(); + return { + time, + value: newValue, + }; + }); + + if (!sellToken) { + throw new Error('Sell token not found'); + } + + const gasPrices = await fetchGasPriceFromPrometheus(); + if (!gasPrices) { + throw new Error('Gas prices not found'); + } + + const estimatedFillPrice = await getEstimatedFillPrices({ + chainId, + sellToken: order.sellToken, + buyToken: order.buyToken, + orderGas: gasAmountString, + gasPricesGwei: gasPrices, + sellTokenPriceInEthWei: sellTokenPriceInWei, + limitPrice: { + sellAmount: order.sellAmount, + buyAmount: order.buyAmount, + }, + }); + + reply.header( + CACHE_CONTROL_HEADER, + getCacheControlHeaderValue(CACHE_SECONDS) + ); + + reply.send(estimatedFillPrice); + } + ); +}; + +export default root; diff --git a/apps/api/src/app/routes/__chainId/orders/__oderId/marketPrice.ts b/apps/api/src/app/routes/__chainId/orders/__oderId/marketPrice.ts new file mode 100644 index 00000000..ac840f07 --- /dev/null +++ b/apps/api/src/app/routes/__chainId/orders/__oderId/marketPrice.ts @@ -0,0 +1,114 @@ +import { SlippageService, slippageServiceSymbol } from '@cowprotocol/services'; + +import { ChainIdSchema, OrderIdSchema } from '../../../../schemas'; +import { FastifyPluginAsync } from 'fastify'; +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; +import { apiContainer } from '../../../../inversify.config'; +import { + CACHE_CONTROL_HEADER, + getCacheControlHeaderValue, +} from '../../../../../utils/cache'; +import { OrderBookApi, SupportedChainId } from '@cowprotocol/cow-sdk'; +import { Big, RoundingMode } from 'bigdecimal.js'; +import { get24HourRange, getLast24HourRange } from '../../../../../utils/date'; +import * as process from 'node:process'; + +import { fetchTokenHistory } from '../../../../../utils/alchemy'; + +const CACHE_SECONDS = 120; + +const routeSchema = { + type: 'object', + required: ['chainId'], + additionalProperties: false, + properties: { + chainId: ChainIdSchema, + }, +} as const satisfies JSONSchema; + +const gasCostQueryStringSchema = { + type: 'object', + properties: { + orderId: OrderIdSchema, + }, +} as const satisfies JSONSchema; + +const gasCostSuccessSchema = { + type: 'array', + items: { + type: 'object', + required: ['time', 'value'], + properties: { + time: { + type: 'number', + description: 'Unix timestamp in seconds', + }, + value: { + type: 'string', + description: 'Gas cost expressed in sell token decimals', + }, + }, + }, +} as const satisfies JSONSchema; + +type RouteSchema = FromSchema; + +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.get<{ + Params: RouteSchema; + Querystring: FromSchema; + Reply: FromSchema; + }>( + '/marketPrice', + { + schema: { + description: 'Retrieve 24h gas cost time series in 5-minute intervals', + tags: ['orders'], + params: routeSchema, + querystring: gasCostQueryStringSchema, + response: { + '2XX': gasCostSuccessSchema, + }, + }, + }, + async function (request, reply) { + const { chainId } = request.params; + const orderId = request.query.orderId as string; + fastify.log.info( + `Get gas cost time series for chain ${chainId} in sell token` + ); + const { start, end } = getLast24HourRange(); + const startTime = new Date(start * 1000); + const endTime = new Date(end * 1000); + const orderBookApi = new OrderBookApi({chainId, env:'prod'}) + const order = await orderBookApi.getOrder(orderId as string); + + const authToken = process.env.ALCHEMY_API_KEY as string; + const sellTokenHistory = await fetchTokenHistory(order.sellToken, startTime, endTime, authToken, chainId); + const buyTokenHistory = await fetchTokenHistory(order.buyToken, startTime, endTime, authToken, chainId); + const dataPoints = []; + if (sellTokenHistory && buyTokenHistory) { + // TODO: use a wiser approach here + const length = Math.min(sellTokenHistory.length, buyTokenHistory.length); + for (let i = 0; i < length; i++) { + const sellTokenPrice = new Big(sellTokenHistory[i].value.toString()); + const buyTokenPrice = new Big(buyTokenHistory[i].value.toString()); + const marketPrice = buyTokenPrice.divide(sellTokenPrice, 20, RoundingMode.HALF_UP); + dataPoints.push({ + value: marketPrice.toString(), + time: new Date(sellTokenHistory[i].timestamp).getTime() + }); + } + } + + reply.header( + CACHE_CONTROL_HEADER, + getCacheControlHeaderValue(CACHE_SECONDS) + ); + + reply.send(dataPoints); + } + ); +}; + +export default root; diff --git a/apps/api/src/app/routes/__chainId/orders/__oderId/statusEvents.ts b/apps/api/src/app/routes/__chainId/orders/__oderId/statusEvents.ts new file mode 100644 index 00000000..47e86711 --- /dev/null +++ b/apps/api/src/app/routes/__chainId/orders/__oderId/statusEvents.ts @@ -0,0 +1,104 @@ +import { SlippageService, slippageServiceSymbol } from '@cowprotocol/services'; + +import { ChainIdSchema, OrderIdSchema } from '../../../../schemas'; +import { FastifyPluginAsync } from 'fastify'; +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; +import { apiContainer } from '../../../../inversify.config'; +import { + CACHE_CONTROL_HEADER, + getCacheControlHeaderValue, +} from '../../../../../utils/cache'; +import { OrderStatus } from '@cowprotocol/cow-sdk'; +import { getOrderEvents } from '../getOrderEvents'; + +const CACHE_SECONDS = 120; + +const routeSchema = { + type: 'object', + required: ['chainId' /*'orderId'*/], + additionalProperties: false, + properties: { + chainId: ChainIdSchema, + // orderId: OrderIdSchema, + }, +} as const satisfies JSONSchema; + +const gasQueryStringSchema = { + type: 'object', + required: ['orderId'], + properties: { + orderId: OrderIdSchema, + }, +} as const satisfies JSONSchema; + +const gasSuccessSchema = { + type: 'array', + items: { + type: 'object', + required: ['time', 'value'], + additionalProperties: false, + properties: { + time: { + type: 'number', + description: 'Unix timestamp in seconds', + }, + value: { + type: 'string', + enum: [ + 'created', + 'ready', + 'filtered', + 'invalid', + 'executing', + 'considered', + 'traded', + 'cancelled', + ], + description: 'Order status event', + }, + }, + }, +} as const satisfies JSONSchema; + +type RouteSchema = FromSchema; + +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.get<{ + Params: RouteSchema; + Querystring: FromSchema; + Reply: FromSchema; + }>( + '/statusEvents', + { + schema: { + description: 'Retrieve 24h gas cost time series in 5-minute intervals', + tags: ['orders'], + params: routeSchema, + querystring: gasQueryStringSchema, + response: { + '2XX': gasSuccessSchema, + }, + }, + }, + async function (request, reply) { + const { chainId } = request.params; + fastify.log.info( + `Get gas cost time series for chain ${chainId} in sell token` + ); + + const { orderId } = request.query; + + // TODO: Implement the actual order status events + const events = await getOrderEvents(chainId, orderId); + + reply.header( + CACHE_CONTROL_HEADER, + getCacheControlHeaderValue(CACHE_SECONDS) + ); + + reply.send(events); + } + ); +}; + +export default root; diff --git a/apps/api/src/app/routes/__chainId/orders/getEstimatedFillPrices.test.ts b/apps/api/src/app/routes/__chainId/orders/getEstimatedFillPrices.test.ts new file mode 100644 index 00000000..e902f02e --- /dev/null +++ b/apps/api/src/app/routes/__chainId/orders/getEstimatedFillPrices.test.ts @@ -0,0 +1,120 @@ +import { + getEstimatedFillPrices, + GetEstimatedFillPricesParams, +} from './getEstimatedFillPrices'; +import { SupportedChainId } from '@cowprotocol/cow-sdk'; + +describe('getEstimatedFillPrices', () => { + it.only('should calculate estimated fill prices correctly for simple values', async () => { + const params: GetEstimatedFillPricesParams = { + chainId: SupportedChainId.MAINNET, + sellToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI + buyToken: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', // WBTC + orderGas: '100000', // 100k gas + gasPricesGwei: [ + { time: 100, value: '50' }, // 50 GWEI + { time: 160, value: '60' }, // 60 GWEI + { time: 220, value: '55' }, // 55 GWEI + ], + sellTokenPriceInEthWei: [ + { time: 100, value: '0.0005' }, // 0.0005 DAI per ETH --> 2000 DAI per WETH + { time: 200, value: '0.001' }, // 0.001 DAI per ETH --> 1000 DAI per WETH + ], + limitPrice: { + sellAmount: '100000000000000000000', // 100 DAI + buyAmount: '1000000000000000', // 0.001 WBTC (price = 100K DAI) + }, + }; + + const result = await getEstimatedFillPrices(params); + + expect(result).toHaveLength(2); + expect(result).toEqual([ + { + time: 100, + // First point: + // Gas cost = 50 GWEI * 100k * 1 ETH = 0.005 ETH = 0.005 tokens + // Total sell amount = 1 + 0.005 = 1.005 tokens + // Price = 1.005 / 2 = 0.5025 + value: '0.50000025', + }, + { + time: 200, + // Second point: + // Gas cost = 55 GWEI * 100k * 2 ETH = 0.011 ETH = 0.0055 tokens + // Total sell amount = 1 + 0.0055 = 1.0055 tokens + // Price = 1.0055 / 2 = 0.50275 + value: '0.5000001375', + }, + ]); + }); + + it('should handle empty price arrays', async () => { + const params: GetEstimatedFillPricesParams = { + chainId: SupportedChainId.MAINNET, + sellToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI + buyToken: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', // WBTC + orderGas: '100000', + gasPricesGwei: [], + sellTokenPriceInEthWei: [], + limitPrice: { + sellAmount: '1000000000000000000', + buyAmount: '2000000000000000000', + }, + }; + + const result = await getEstimatedFillPrices(params); + expect(result).toHaveLength(0); + }); + + it('should match closest gas price points correctly', async () => { + const params: GetEstimatedFillPricesParams = { + chainId: SupportedChainId.MAINNET, + sellToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI + buyToken: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', // WBTC + orderGas: '100000', + gasPricesGwei: [ + { time: 90, value: '50000000000' }, // 50 GWEI + { time: 150, value: '60000000000' }, // 60 GWEI + { time: 210, value: '55000000000' }, // 55 GWEI + ], + sellTokenPriceInEthWei: [ + { time: 100, value: '1000000000000000000' }, // Should match with 50 GWEI (closest to 90) + { time: 200, value: '2000000000000000000' }, // Should match with 55 GWEI (closest to 210) + ], + limitPrice: { + sellAmount: '1000000000000000000', + buyAmount: '2000000000000000000', + }, + }; + + const result = await getEstimatedFillPrices(params); + expect(result).toHaveLength(2); + // Verify that the closest points were matched correctly + expect(result[0].time).toBe(100); + expect(result[1].time).toBe(200); + }); + + it('should handle edge case with single price point', async () => { + const params: GetEstimatedFillPricesParams = { + chainId: SupportedChainId.MAINNET, + sellToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI + buyToken: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', // WBTC + orderGas: '100000', + gasPricesGwei: [ + { time: 100, value: '50000000000' }, // 50 GWEI + ], + sellTokenPriceInEthWei: [ + { time: 100, value: '1000000000000000000' }, // 1 ETH + ], + limitPrice: { + sellAmount: '1000000000000000000', + buyAmount: '2000000000000000000', + }, + }; + + const result = await getEstimatedFillPrices(params); + expect(result).toHaveLength(1); + expect(result[0].time).toBe(100); + }); +}); diff --git a/apps/api/src/app/routes/__chainId/orders/getEstimatedFillPrices.ts b/apps/api/src/app/routes/__chainId/orders/getEstimatedFillPrices.ts new file mode 100644 index 00000000..70916f83 --- /dev/null +++ b/apps/api/src/app/routes/__chainId/orders/getEstimatedFillPrices.ts @@ -0,0 +1,172 @@ +import { + Erc20Repository, + erc20RepositorySymbol, +} from '@cowprotocol/repositories'; +import { EstimatedFillPrice, ValuePoint } from './types'; +import BigNumber from 'bignumber.js'; +import { apiContainer } from '../../../inversify.config'; +import { SupportedChainId } from '@cowprotocol/cow-sdk'; + +export type GetEstimatedFillPricesParams = { + chainId: SupportedChainId; + sellToken: string; + buyToken: string; + orderGas: string; // We have: from API + gasPricesGwei: ValuePoint[]; // We have (every 1min) + + sellTokenPriceInEthWei: ValuePoint[]; // TODO: Multiply price of token by gasPrice --> we get gas cost at a moment in time + + limitPrice: { + sellAmount: string; + buyAmount: string; + }; +}; + +export async function getEstimatedFillPrices( + params: GetEstimatedFillPricesParams +): Promise { + // console.log('params', { + // gasPricesGwei: params.gasPricesGwei[0], + // sellTokenPriceInEthWei: params.sellTokenPriceInEthWei[0], + // limitPrice: params.limitPrice, + // orderGas: params.orderGas, + // }); + const { + chainId, + sellToken: sellTokenAddress, + buyToken: buyTokenAddress, + limitPrice, + orderGas: orderGasString, + gasPricesGwei, + sellTokenPriceInEthWei, + } = params; + + // Match closest points first + const matchedPrices = matchClosestPrices( + sellTokenPriceInEthWei, + gasPricesGwei + ); + + // Calculate the decimal difference between the sell and buy token + const erc20Repository: Erc20Repository = apiContainer.get( + erc20RepositorySymbol + ); + const sellToken = await erc20Repository.get(chainId, sellTokenAddress); + const buyToken = await erc20Repository.get(chainId, buyTokenAddress); + + const sellTokenDecimals = sellToken?.decimals || 18; + const buyTokenDecimals = buyToken?.decimals || 18; + const tokenDecimalsDifference = sellTokenDecimals - buyTokenDecimals; + + // Print first 10 matched prices + // console.log( + // 'gasPricesGwei', + // gasPricesGwei + // .slice(0, 10) + // .map((p) => p.value) + // .join(', ') + // ); + // console.log( + // 'matchedPrices', + // matchedPrices + // .slice(0, 10) + // .map((p) => p.value) + // .join(', ') + // ); + + console.log( + 'gasPricesGwei times', + new Date(gasPricesGwei[0].time).toISOString(), + new Date(gasPricesGwei[gasPricesGwei.length - 1].time).toISOString() + ); + console.log( + 'matchedPrices times', + new Date(matchedPrices[0].time).toISOString(), + new Date(matchedPrices[matchedPrices.length - 1].time).toISOString() + ); + console.log( + 'sellTokenPriceInEthWei', + new Date(sellTokenPriceInEthWei[0].time).toISOString(), + new Date( + sellTokenPriceInEthWei[sellTokenPriceInEthWei.length - 1].time + ).toISOString() + ); + + // Process each matched point + return matchedPrices.map((gasPrice, index) => { + const tokenPriceInEthWei = sellTokenPriceInEthWei[index]; + + // Gas price in weis per unit of gas + // const gasPriceInWei = new BigNumber(gasPrice.value).multipliedBy( + // new BigNumber(1e9) + // ); + + // const gasCostInSellToken = new BigNumber(gasPrice.value) + // .multipliedBy(orderGasString) + // .dividedBy(tokenPrice.value) + // .dividedBy(new BigNumber(1e9)); // * 1e18 (to convert to weis) / 1e9 (cause is G + + // Get gas price in ETH (weis) + const gasPriceInWei = new BigNumber(gasPrice.value).multipliedBy(1e9); + + // Calculate the costs in ETH (weis) + const gasCostInWei = gasPriceInWei.multipliedBy(orderGasString); + + // Calculate the costs in the sell token (weis) + const gasCostInSellToken = gasCostInWei.dividedBy(tokenPriceInEthWei.value); + + // Add gas cost to sell amount + const sellAmountIncludingCost = gasCostInSellToken.plus( + limitPrice.sellAmount + ); + + // Calculate the price (including costs) + const priceIncludingCosts = sellAmountIncludingCost + .dividedBy(10 ** tokenDecimalsDifference) + .div(limitPrice.buyAmount); + + // if (index === 0) { + // console.log('data', { + // limitPrice, + // tokenPriceInEthWei, + // orderGasString, + // gasPrice: gasPrice.value, + // gasPriceInWei: gasPriceInWei.toString(), + // gasCostInWei: gasCostInWei.toString(), + // gasCostInSellToken: gasCostInSellToken.toString(), + // sellAmountIncludingCost: sellAmountIncludingCost.toString(), + // priceIncludingCosts: priceIncludingCosts.toString(), + // }); + // } + + return { + time: tokenPriceInEthWei.time, + fillPrice: priceIncludingCosts.toString(), + gasPriceGwei: gasPrice.value, + sellTokenPriceInEthWei: tokenPriceInEthWei.value, + }; + }); +} + +function matchClosestPrices( + tokenPrices: ValuePoint[], + gasPrices: ValuePoint[] +): ValuePoint[] { + const matched: ValuePoint[] = []; + let gasIndex = 0; + + for (const tokenPrice of tokenPrices) { + // Find the closest gas price point by moving forward until we pass the token price + while ( + gasIndex < gasPrices.length - 1 && + Math.abs(gasPrices[gasIndex + 1].time - tokenPrice.time) < + Math.abs(gasPrices[gasIndex].time - tokenPrice.time) + ) { + gasIndex++; + } + + matched.push(gasPrices[gasIndex]); + } + + return matched; +} diff --git a/apps/api/src/app/routes/__chainId/orders/getOrderEvents.ts b/apps/api/src/app/routes/__chainId/orders/getOrderEvents.ts new file mode 100644 index 00000000..a8d7d3f4 --- /dev/null +++ b/apps/api/src/app/routes/__chainId/orders/getOrderEvents.ts @@ -0,0 +1,39 @@ +import { SupportedChainId } from '@cowprotocol/cow-sdk'; +import { Pool } from 'pg'; // If using node-postgres +import { OrderEvent } from './types'; + +// Database connection +// TODO: do this properly using fastify +const pool = new Pool({ + user: process.env.POSTGRES_USER, + host: process.env.POSTGRES_HOST, + database: 'mainnet', // TODO: make this dynamic based on the chainId. The method passes the chainId + password: process.env.POSTGRES_PASSWORD, + port: Number(process.env.POSTGRES_PORT) || 5432, +}); + +// Example query function +async function executeQuery(query: string, params: any[]) { + try { + const result = await pool.query(query, params); + return result.rows; + } catch (error) { + console.error('Database error:', error); + throw error; + } +} + +export async function getOrderEvents( + chainId: SupportedChainId, + orderId: string +): Promise { + if (chainId !== SupportedChainId.MAINNET) { + throw new Error('Only Mainnet is supported'); + } + + // Check the connection to the DB works + return await executeQuery( + "SELECT timestamp as time, label as value FROM order_events WHERE order_uid = decode($1, 'hex')", + [orderId.substring(2)] + ); +} diff --git a/apps/api/src/app/routes/__chainId/orders/types.ts b/apps/api/src/app/routes/__chainId/orders/types.ts new file mode 100644 index 00000000..febb9da3 --- /dev/null +++ b/apps/api/src/app/routes/__chainId/orders/types.ts @@ -0,0 +1,23 @@ +export interface OrderEvent { + time: number; + value: OrderStatus; +} + +export enum OrderStatus { + CREATED = 'created', + READY = 'ready', + FILTERED = 'filtered', + INVALID = 'invalid', +} + +export interface ValuePoint { + time: number; + value: string; +} + +export interface EstimatedFillPrice { + time: number; + fillPrice: string; + gasPriceGwei: string; + sellTokenPriceInEthWei: string; +} diff --git a/apps/api/src/app/schemas.ts b/apps/api/src/app/schemas.ts index 26241be4..122e04ea 100644 --- a/apps/api/src/app/schemas.ts +++ b/apps/api/src/app/schemas.ts @@ -14,4 +14,11 @@ export const AddressSchema = { pattern: '^0x[a-fA-F0-9]{40}$', } as const; +export const OrderIdSchema = { + title: 'Order ID', + description: 'Order ID', + type: 'string', + pattern: '^0x[a-fA-F0-9]{112}$', +} as const; + export const ETHEREUM_ADDRESS_PATTERN = '^0x[a-fA-F0-9]{40}$'; diff --git a/apps/api/src/utils/alchemy.ts b/apps/api/src/utils/alchemy.ts new file mode 100644 index 00000000..82b8c7d9 --- /dev/null +++ b/apps/api/src/utils/alchemy.ts @@ -0,0 +1,34 @@ +import { SupportedChainId } from '@cowprotocol/cow-sdk'; + +const AlchemyNetworkByChainId: Record = { + [SupportedChainId.MAINNET]: 'eth-mainnet', + [SupportedChainId.GNOSIS_CHAIN]: 'eth-gnosis', + [SupportedChainId.ARBITRUM_ONE]: 'eth-arbitrum', + [SupportedChainId.SEPOLIA]: 'eth-sepolia', + [SupportedChainId.BASE]: 'eth-base', + }; + +export async function fetchTokenHistory(token: string, startTime: Date, endTime: Date, auth_token: string, chain_id: SupportedChainId) { + const options = { + method: 'POST', + headers: {accept: 'application/json', 'content-type': 'application/json', 'Authorization': `Bearer ${auth_token}`}, + body: JSON.stringify({ + startTime: startTime.toISOString(), + endTime: endTime.toISOString(), + interval: '5m', + address: token, + network: AlchemyNetworkByChainId[chain_id], + }) + }; + + console.log(`request=${JSON.stringify(options)}`); + + try { + const response = await fetch('https://api.g.alchemy.com/prices/v1/tokens/historical', options); + const data = await response.json(); + return data.data; + } catch (err) { + console.error(err); + return undefined; + } + } \ No newline at end of file diff --git a/apps/api/src/utils/date.ts b/apps/api/src/utils/date.ts new file mode 100644 index 00000000..4a80a9ac --- /dev/null +++ b/apps/api/src/utils/date.ts @@ -0,0 +1,55 @@ +/** + * Returns start and end timestamps for a given date's 24-hour period, optionally adjusted for timezone + * @param date Date + * @returns Object containing start and end timestamps in seconds + */ +export function get24HourRange(date: Date) { + // Start of day + const start = getStartOfDay(date); + + // End of day (start + 24 hours - 1 millisecond) + const end = getEndOfDay(date); + + return { + start: Math.floor(start.getTime() / 1000), + end: Math.floor(end.getTime() / 1000), + }; +} + +export function getLast24HourRange() { + const dateOffset = (24*60*60*1000); //1 day + const startTime = new Date(); + const start = startTime.setTime(startTime.getTime() - dateOffset); + + return { + start: Math.floor(start/ 1000), + end: Math.floor(new Date().getTime() / 1000), + }; +} + +function getStartOfDay(date: Date): Date { + const start = new Date(date); + start.setHours(0, 0, 0, 0); + + return start; +} + +function getEndOfDay(date: Date): Date { + const end = new Date(date); + end.setHours(23, 59, 59, 999); + + return end; +} + +/** + * Converts a string or Date object to a Date, optionally adjusting for timezone + * @param date Date string or Date object to convert + * @param timezone Optional timezone (e.g. 'America/New_York', 'Europe/Berlin'). Defaults to UTC + * @returns Date object in the specified timezone (or UTC if no timezone provided) + */ + +function toDate(date: string | Date, timezone?: string): Date { + return timezone + ? new Date(date.toLocaleString('en-US', { timeZone: timezone })) + : new Date(date); +} diff --git a/libs/repositories/src/UsdRepository/UsdRepositoryCoingecko.ts b/libs/repositories/src/UsdRepository/UsdRepositoryCoingecko.ts index bc370c25..ff31114b 100644 --- a/libs/repositories/src/UsdRepository/UsdRepositoryCoingecko.ts +++ b/libs/repositories/src/UsdRepository/UsdRepositoryCoingecko.ts @@ -124,4 +124,74 @@ export class UsdRepositoryCoingecko implements UsdRepository { return pricePoints; } + + async getUsdPricesBetween( + chainId: SupportedChainId, + tokenAddress: string, + startTimestamp: number, + endTimestamp: number, + ): Promise { + const platform = COINGECKO_PLATFORMS[chainId]; + if (!platform) { + return null; + } + + const tokenAddressLower = tokenAddress.toLowerCase(); + const daysInterval = Math.floor((endTimestamp - startTimestamp) / (1000 * 60 * 60 * 24)); + // TODO: 5m strategy requires an Enterprise plan + // let priceStrategy: PriceStrategy = '5m'; + // if (daysInterval > 90) { + // priceStrategy = 'daily'; + // } else if (daysInterval >= 2) { + // priceStrategy = 'hourly'; + // } + console.log(`daysInterval: ${daysInterval}`); + // console.log(`priceStrategy: ${priceStrategy}`); + + // Get prices: See https://docs.coingecko.com/reference/contract-address-market-chart + const { data: priceData, response } = await coingeckoProClient.GET( + `/coins/{id}/contract/{contract_address}/market_chart/range`, + { + params: { + path: { + id: platform, + contract_address: tokenAddressLower, + }, + query: { + vs_currency: 'usd', + from: startTimestamp, + to: endTimestamp, + // interval: priceStrategy, + }, + }, + } + ); + + if (response.status === 404 || !priceData) { + return null; + } + await throwIfUnsuccessful( + 'Error getting USD prices from Coingecko', + response + ); + + const volumesMap = + priceData.total_volumes?.reduce((acc, [timestamp, volume]) => { + acc.set(timestamp, volume); + return acc; + }, new Map()) || undefined; + + const prices = priceData.prices; + if (!prices) { + return null; + } + + const pricePoints = prices.map(([timestamp, price]) => ({ + date: new Date(timestamp), + price, + volume: volumesMap?.get(timestamp) ?? 0, + })); + + return pricePoints; + } } diff --git a/libs/repositories/src/gen/cow/cow-api-types.ts b/libs/repositories/src/gen/cow/cow-api-types.ts index 750c50bb..0a06885c 100644 --- a/libs/repositories/src/gen/cow/cow-api-types.ts +++ b/libs/repositories/src/gen/cow/cow-api-types.ts @@ -1209,23 +1209,22 @@ export interface components { * */ availableBalance?: components["schemas"]["TokenAmount"] | null; - /** @description The total amount of `sellToken` that has been executed for this order including fees. + /** @description The total amount of `sellToken` that has been transferred from the user for this order so far. * */ executedSellAmount: components["schemas"]["BigUint"]; - /** @description The total amount of `sellToken` that has been executed for this order without fees. + /** @description The total amount of `sellToken` that has been transferred from the user for this order so far minus tokens that were transferred as part of the signed `fee` of the order. This is only relevant for old orders because now all orders have a signed `fee` of 0 and solvers compute an appropriate fee dynamically at the time of the order execution. * */ executedSellAmountBeforeFees: components["schemas"]["BigUint"]; /** @description The total amount of `buyToken` that has been executed for this order. * */ executedBuyAmount: components["schemas"]["BigUint"]; - /** @description The total amount of fees that have been executed for this order. */ + /** @description [DEPRECATED] The total amount of the user signed `fee` that have been executed for this order. This value is only non-negative for very old orders. + * */ executedFeeAmount: components["schemas"]["BigUint"]; /** @description Has this order been invalidated? */ invalidated: boolean; /** @description Order status. */ status: components["schemas"]["OrderStatus"]; - /** @description Amount that the signed fee would be without subsidies. */ - fullFeeAmount?: components["schemas"]["TokenAmount"]; /** @description Liquidity orders are functionally the same as normal smart contract * orders but are not placed with the intent of actively getting * traded. Instead they facilitate the trade of normal orders by @@ -1245,8 +1244,11 @@ export interface components { /** @description There is some data only available for orders that are placed on-chain. This data can be found in this object. * */ onchainOrderData?: components["schemas"]["OnchainOrderData"]; - /** @description Surplus fee that the limit order was executed with. */ - executedSurplusFee?: components["schemas"]["BigUint"] | null; + /** @description Total fee charged for execution of the order. Contains network fee and protocol fees. This takes into account the historic static fee signed by the user and the new dynamic fee computed by solvers. + * */ + executedFee?: components["schemas"]["BigUint"]; + /** @description Token the executed fee was captured in. */ + executedFeeToken?: components["schemas"]["Address"]; /** @description Full `appData`, which the contract-level `appData` is a hash of. See `OrderCreation` for more information. * */ fullAppData?: string | null; @@ -1316,10 +1318,6 @@ export interface components { /** @description The block number for the auction. Orders and prices are guaranteed to be valid on this block. Proposed settlements should be valid for this block as well. * */ block?: number; - /** @description The latest block on which a settlement has been processed. - * **NOTE**: Under certain conditions it is possible for a settlement to have been mined as part of `block` but not have yet been processed. - * */ - latestSettlementBlock?: number; /** @description The solvable orders included in the auction. * */ orders?: components["schemas"]["AuctionOrder"][]; @@ -1436,7 +1434,7 @@ export interface components { PreSignature: string; OrderPostError: { /** @enum {string} */ - errorType: "DuplicatedOrder" | "QuoteNotFound" | "QuoteNotVerified" | "InvalidQuote" | "MissingFrom" | "WrongOwner" | "InvalidEip1271Signature" | "InsufficientBalance" | "InsufficientAllowance" | "InvalidSignature" | "SellAmountOverflow" | "TransferSimulationFailed" | "ZeroAmount" | "IncompatibleSigningScheme" | "TooManyLimitOrders" | "TooMuchGas" | "UnsupportedBuyTokenDestination" | "UnsupportedSellTokenSource" | "UnsupportedOrderType" | "InsufficientValidTo" | "ExcessiveValidTo" | "InvalidNativeSellToken" | "SameBuyAndSellToken" | "UnsupportedToken" | "InvalidAppData" | "AppDataHashMismatch" | "AppdataFromMismatch"; + errorType: "DuplicatedOrder" | "QuoteNotFound" | "QuoteNotVerified" | "InvalidQuote" | "MissingFrom" | "WrongOwner" | "InvalidEip1271Signature" | "InsufficientBalance" | "InsufficientAllowance" | "InvalidSignature" | "SellAmountOverflow" | "TransferSimulationFailed" | "ZeroAmount" | "IncompatibleSigningScheme" | "TooManyLimitOrders" | "TooMuchGas" | "UnsupportedBuyTokenDestination" | "UnsupportedSellTokenSource" | "UnsupportedOrderType" | "InsufficientValidTo" | "ExcessiveValidTo" | "InvalidNativeSellToken" | "SameBuyAndSellToken" | "UnsupportedToken" | "InvalidAppData" | "AppDataHashMismatch" | "AppdataFromMismatch" | "OldOrderActivelyBidOn"; description: string; }; OrderCancellationError: { @@ -1585,6 +1583,8 @@ export interface components { id?: components["schemas"]["UID"]; executedAmount?: components["schemas"]["BigUint"]; }[]; + /** @description whether the solution is a winner (received the right to get executed) or not */ + isWinner?: boolean; }; /** @description The estimated native price for the token * */ diff --git a/libs/services/src/UsdService/UsdService.ts b/libs/services/src/UsdService/UsdService.ts index 75cd0d4d..ba8464a3 100644 --- a/libs/services/src/UsdService/UsdService.ts +++ b/libs/services/src/UsdService/UsdService.ts @@ -1,7 +1,7 @@ import { UsdRepository, usdRepositorySymbol, - SupportedChainId, + SupportedChainId, PriceStrategy, PricePoint } from '@cowprotocol/repositories'; import { injectable, inject } from 'inversify'; diff --git a/package.json b/package.json index 8da422fb..7733c62f 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "abstract-cache-redis": "^2.0.0", "amqplib": "^0.10.4", "axios": "^1.0.0", + "bigdecimal.js": "^1.3.1", "bignumber.js": "^9.1.2", "ethers": "^5.7.2", "fastify": "~4.13.0", @@ -55,7 +56,7 @@ "node-fetch": "^3.3.2", "node-telegram-bot-api": "^0.65.1", "openapi-fetch": "^0.10.2", - "pg": "^8.13.1", + "pg": "^8.14.1", "reflect-metadata": "^0.2.2", "tslib": "^2.3.0", "typeorm": "^0.3.17", @@ -79,6 +80,7 @@ "@types/mustache": "^4.2.5", "@types/node": "^20.14.11", "@types/node-telegram-bot-api": "^0.64.6", + "@types/pg": "^8.11.11", "@types/tap": "^15.0.5", "@typescript-eslint/eslint-plugin": "^5.58.0", "@typescript-eslint/parser": "^5.58.0", diff --git a/redocly.yaml b/redocly.yaml index 7abf6bfa..ea5c0f04 100644 --- a/redocly.yaml +++ b/redocly.yaml @@ -6,20 +6,20 @@ apis: x-openapi-ts: output: ./libs/repositories/src/gen/cow/cow-api-types.ts - # Public API Swagger JSON - coingecko-public@v3: - root: https://docs.coingecko.com/openapi/65bf9cabb0951b0072e2cade - x-openapi-ts: - output: ./libs/repositories/src/gen/coingecko/coingecko-public-types.ts + # # Public API Swagger JSON + # coingecko-public@v3: + # root: https://docs.coingecko.com/openapi/65bf9cabb0951b0072e2cade + # x-openapi-ts: + # output: ./libs/repositories/src/gen/coingecko/coingecko-public-types.ts - # CoinGecko API Endpoints (PRO) - coingecko-pro@v3: - root: https://docs.coingecko.com/openapi/6584ea6ce07e130056b1af99 - x-openapi-ts: - output: ./libs/repositories/src/gen/coingecko/coingecko-pro-types.ts + # # CoinGecko API Endpoints (PRO) + # coingecko-pro@v3: + # root: https://docs.coingecko.com/openapi/6584ea6ce07e130056b1af99 + # x-openapi-ts: + # output: ./libs/repositories/src/gen/coingecko/coingecko-pro-types.ts - # Onchain DEX API (GeckoTerminal) Endpoints - coingecko-dex@v3: - root: https://docs.coingecko.com/openapi/6585013ec2907b0031346aa4 - x-openapi-ts: - output: ./libs/repositories/src/gen/coingecko/coingecko-dex-types.ts + # # Onchain DEX API (GeckoTerminal) Endpoints + # coingecko-dex@v3: + # root: https://docs.coingecko.com/openapi/6585013ec2907b0031346aa4 + # x-openapi-ts: + # output: ./libs/repositories/src/gen/coingecko/coingecko-dex-types.ts diff --git a/tsconfig.base.json b/tsconfig.base.json index 0020d49b..516fb031 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -8,7 +8,7 @@ "emitDecoratorMetadata": true, "experimentalDecorators": true, "importHelpers": true, - "target": "es2015", + "target": "ES2020", "module": "esnext", "lib": ["es2020", "dom"], "skipLibCheck": true, diff --git a/yarn.lock b/yarn.lock index 84fb5766..5cccf1a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,7 +18,7 @@ "@adraffy/ens-normalize@1.10.0": version "1.10.0" - resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" + resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz" integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== "@ampproject/remapping@^2.2.0": @@ -38,7 +38,7 @@ "@babel/code-frame@^7.22.13": version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz" integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== dependencies: "@babel/highlight" "^7.24.7" @@ -255,7 +255,7 @@ "@babel/helper-validator-identifier@^7.24.7": version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz" integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== "@babel/helper-validator-option@^7.22.5": @@ -293,7 +293,7 @@ "@babel/highlight@^7.24.7": version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz" integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== dependencies: "@babel/helper-validator-identifier" "^7.24.7" @@ -1080,19 +1080,19 @@ "@cowprotocol/cms@^0.3.0-RC.4": version "0.3.0-RC.4" - resolved "https://registry.yarnpkg.com/@cowprotocol/cms/-/cms-0.3.0-RC.4.tgz#cfe28820f88e555891c8fc555814beaf6ba14d46" + resolved "https://registry.npmjs.org/@cowprotocol/cms/-/cms-0.3.0-RC.4.tgz" integrity sha512-6E1D36xaC8Cpecuu1atDGFr8XmNQwcSef8xv5q9/uS11lW150HjiEYeGBr7IObeky5OS2st5zpY0Ll8FOgReZA== dependencies: openapi-fetch "^0.9.3" "@cowprotocol/contracts@^1.6.0": version "1.6.0" - resolved "https://registry.yarnpkg.com/@cowprotocol/contracts/-/contracts-1.6.0.tgz#d0fc83ed8c624b968d1a68bb5c74712c11ec81e0" + resolved "https://registry.npmjs.org/@cowprotocol/contracts/-/contracts-1.6.0.tgz" integrity sha512-+UKhYRzkvnqqviBru5D3btTLYc743n0O5YTG+wpYwGl4fb7VNKBkFHe28C5Mf1DF/kOfmqfu+0IAvX9Vuq5Dqw== "@cowprotocol/cow-sdk@^5.7.1": version "5.7.1" - resolved "https://registry.yarnpkg.com/@cowprotocol/cow-sdk/-/cow-sdk-5.7.1.tgz#22b556b79c949a3c5a65ee87f188a477f29d76eb" + resolved "https://registry.npmjs.org/@cowprotocol/cow-sdk/-/cow-sdk-5.7.1.tgz" integrity sha512-1SKzf6hqLEUP3if+Ki6eweSWcUA7hDyFcmUW2tf6a0XROwl9ktNHWP7dJ09zMrnFn6k03DqoYvKun1i+WS1D7Q== dependencies: "@cowprotocol/contracts" "^1.6.0" @@ -1757,7 +1757,7 @@ "@fastify/caching@^8.3.0": version "8.3.0" - resolved "https://registry.yarnpkg.com/@fastify/caching/-/caching-8.3.0.tgz#0954aa996424c49aade8f63bbbe5acb89a921662" + resolved "https://registry.npmjs.org/@fastify/caching/-/caching-8.3.0.tgz" integrity sha512-wxlQS2C9omy7+Aq33XDaHJWO0wF3DH2QFBD/ZHMJnWbL2buUDsjzCNg0TbSbEMHyFi/NiryYYAXVCoFCD7nFTA== dependencies: abstract-cache "^1.0.1" @@ -1808,7 +1808,7 @@ "@fastify/redis@^6.2.0": version "6.2.0" - resolved "https://registry.yarnpkg.com/@fastify/redis/-/redis-6.2.0.tgz#6da1f272846200e666749be26ac968788c698802" + resolved "https://registry.npmjs.org/@fastify/redis/-/redis-6.2.0.tgz" integrity sha512-0M4oTYRJz/ETPdfXvs/ToFI0ZNFjrz1jYFxEr+wHgnW6hswDsLDs+gxLMff2cb5Fegg3siG4hJzhmvvpvqqqbA== dependencies: fastify-plugin "^4.0.0" @@ -1907,7 +1907,7 @@ "@ioredis/commands@^1.1.1": version "1.2.0" - resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" + resolved "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz" integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== "@istanbuljs/load-nyc-config@^1.0.0": @@ -2148,9 +2148,9 @@ integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.15" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + version "1.5.0" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -2222,14 +2222,14 @@ "@noble/curves@1.4.0": version "1.4.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.0.tgz#f05771ef64da724997f69ee1261b2417a49522d6" + resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz" integrity sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg== dependencies: "@noble/hashes" "1.4.0" "@noble/curves@^1.4.0", "@noble/curves@~1.4.0": version "1.4.2" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz" integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== dependencies: "@noble/hashes" "1.4.0" @@ -2241,7 +2241,7 @@ "@noble/hashes@1.4.0", "@noble/hashes@^1.4.0", "@noble/hashes@~1.4.0": version "1.4.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== "@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": @@ -2715,7 +2715,7 @@ "@redocly/ajv@^8.11.0": version "8.11.0" - resolved "https://registry.yarnpkg.com/@redocly/ajv/-/ajv-8.11.0.tgz#2fad322888dc0113af026e08fceb3e71aae495ae" + resolved "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.0.tgz" integrity sha512-9GWx27t7xWhDIR02PA18nzBdLcKQRgc46xNQvjFkrYk4UOmvKhJ/dawwiX0cCOeetN5LcaaiqQbVOWYK62SGHw== dependencies: fast-deep-equal "^3.1.1" @@ -2725,12 +2725,12 @@ "@redocly/config@^0.6.2": version "0.6.2" - resolved "https://registry.yarnpkg.com/@redocly/config/-/config-0.6.2.tgz#b5180ccb407673ee048b818c3be9a4f9d0636a64" + resolved "https://registry.npmjs.org/@redocly/config/-/config-0.6.2.tgz" integrity sha512-c3K5u64eMnr2ootPcpEI0ioIRLE8QP8ptvLxG9MwAmb2sU8HMRfVwXDU3AZiMVY2w4Ts0mDc+Xv4HTIk8DRqFw== "@redocly/openapi-core@^1.16.0": version "1.17.1" - resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.17.1.tgz#d18c5223e5b578d64d789c4101b96cbb589162dc" + resolved "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.17.1.tgz" integrity sha512-PQxDLLNk5cBatJBBxvfk49HFw/nVozw1XZ6Dw/GX0Tviq+WxeEjEuLAKfnLVvb5L0wgs4TNmVG4Y+JyofSPu1A== dependencies: "@redocly/ajv" "^8.11.0" @@ -2792,7 +2792,7 @@ "@scure/base@~1.1.6": version "1.1.7" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.7.tgz#fe973311a5c6267846aa131bc72e96c5d40d2b30" + resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz" integrity sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g== "@scure/bip32@1.1.5": @@ -2806,7 +2806,7 @@ "@scure/bip32@1.4.0": version "1.4.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz" integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== dependencies: "@noble/curves" "~1.4.0" @@ -2823,7 +2823,7 @@ "@scure/bip39@1.3.0": version "1.3.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" + resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz" integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== dependencies: "@noble/hashes" "~1.4.0" @@ -2935,7 +2935,7 @@ "@types/bignumber.js@^5.0.0": version "5.0.0" - resolved "https://registry.yarnpkg.com/@types/bignumber.js/-/bignumber.js-5.0.0.tgz#d9f1a378509f3010a3255e9cc822ad0eeb4ab969" + resolved "https://registry.npmjs.org/@types/bignumber.js/-/bignumber.js-5.0.0.tgz" integrity sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA== dependencies: bignumber.js "*" @@ -2991,12 +2991,12 @@ "@types/ms@^0.7.34": version "0.7.34" - resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" + resolved "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz" integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== "@types/mustache@^4.2.5": version "4.2.5" - resolved "https://registry.yarnpkg.com/@types/mustache/-/mustache-4.2.5.tgz#9129f0d6857f976e00e171bbb3460e4b702f84ef" + resolved "https://registry.npmjs.org/@types/mustache/-/mustache-4.2.5.tgz" integrity sha512-PLwiVvTBg59tGFL/8VpcGvqOu3L4OuveNvPi0EYbWchRdEVP++yRUXJPFl+CApKEq13017/4Nf7aQ5lTtHUNsA== "@types/node-telegram-bot-api@^0.64.6": @@ -3007,16 +3007,9 @@ "@types/node" "*" "@types/request" "*" -"@types/node@*": - version "18.19.32" - resolved "https://registry.npmjs.org/@types/node/-/node-18.19.32.tgz" - integrity sha512-2bkg93YBSDKk8DLmmHnmj/Rwr18TLx7/n+I23BigFwgexUJoMHZOd8X1OFxuF/W3NN0S2W2E5sVabI5CPinNvA== - dependencies: - undici-types "~5.26.4" - -"@types/node@^20.14.11": +"@types/node@*", "@types/node@^20.14.11": version "20.14.11" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.11.tgz#09b300423343460455043ddd4d0ded6ac579b74b" + resolved "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz" integrity sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA== dependencies: undici-types "~5.26.4" @@ -3026,6 +3019,15 @@ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/pg@^8.11.11": + version "8.11.11" + resolved "https://registry.npmjs.org/@types/pg/-/pg-8.11.11.tgz" + integrity sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw== + dependencies: + "@types/node" "*" + pg-protocol "*" + pg-types "^4.0.1" + "@types/prettier@^2.1.1", "@types/prettier@^2.1.5": version "2.7.3" resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz" @@ -3274,7 +3276,7 @@ abitype@1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.5.tgz#29d0daa3eea867ca90f7e4123144c1d1270774b6" + resolved "https://registry.npmjs.org/abitype/-/abitype-1.0.5.tgz" integrity sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw== abort-controller@^3.0.0: @@ -3286,14 +3288,14 @@ abort-controller@^3.0.0: abstract-cache-redis@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/abstract-cache-redis/-/abstract-cache-redis-2.0.0.tgz#ae7e215f0b7dd92cd266797f2702a52be6d3d37f" + resolved "https://registry.npmjs.org/abstract-cache-redis/-/abstract-cache-redis-2.0.0.tgz" integrity sha512-RlEniQUnIFCnh7U9S4kdDM7/uhpkl8KH5EdFplH7ntwze4voH8VhvaLXwc0mKQqL/daO9X6qULh8bWpgNrUtGg== dependencies: ioredis "^4.26.0" abstract-cache@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/abstract-cache/-/abstract-cache-1.0.1.tgz#136151becf5c32e0ea27f78728d073d8fe07932a" + resolved "https://registry.npmjs.org/abstract-cache/-/abstract-cache-1.0.1.tgz" integrity sha512-EfUeMhRUbG5bVVbrSY/ogLlFXoyfMAPxMlSP7wrEqH53d+59r2foVy9a5KjmprLKFLOfPQCNKEfpBN/nQ76chw== dependencies: clone "^2.1.1" @@ -3316,9 +3318,9 @@ acorn-walk@^8.1.1: integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== acorn@^8.4.1, acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + version "8.14.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz" + integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== address@^1.0.1: version "1.2.2" @@ -3332,7 +3334,7 @@ aes-js@3.0.0: agent-base@^7.0.2: version "7.1.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz" integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== dependencies: debug "^4.3.4" @@ -3696,9 +3698,14 @@ big.js@^5.2.2: resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== +bigdecimal.js@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/bigdecimal.js/-/bigdecimal.js-1.3.1.tgz#c2f09d53a6298c26493dd236692aebb751f29223" + integrity sha512-ovAaZP2zB3N+qdY/c7FI19FiMUl4wpM/x8IqL17jiUBwqacP5rY0xJoCHjTAF+++g9+hRGqIpQXpX893Bd8x4Q== + bignumber.js@*, bignumber.js@^9.1.2: version "9.1.2" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" + resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz" integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== binary-extensions@^2.0.0: @@ -3949,7 +3956,7 @@ cliui@^8.0.1: clone@2.x, clone@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + resolved "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz" integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== close-with-grace@^1.1.0: @@ -3959,7 +3966,7 @@ close-with-grace@^1.1.0: cluster-key-slot@^1.1.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" + resolved "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz" integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== co@^4.6.0: @@ -3998,7 +4005,7 @@ color-name@~1.1.4: colorette@^1.2.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" + resolved "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== colorette@^2.0.7: @@ -4153,7 +4160,7 @@ dashdash@^1.12.0: data-uri-to-buffer@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz" integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== data-view-buffer@^1.0.1: @@ -4269,12 +4276,12 @@ delayed-stream@~1.0.0: denque@^1.1.0: version "1.5.1" - resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" + resolved "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz" integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== denque@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" + resolved "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz" integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== depd@2.0.0: @@ -4846,7 +4853,7 @@ fast-copy@^3.0.0: fast-copy@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35" + resolved "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz" integrity sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ== fast-decode-uri-component@^1.0.1: @@ -4927,7 +4934,7 @@ fast-uri@^2.0.0, fast-uri@^2.1.0: "fastify-caching-deprecated@npm:fastify-caching@6.2.0": version "6.2.0" - resolved "https://registry.yarnpkg.com/fastify-caching/-/fastify-caching-6.2.0.tgz#6a7649509c709005098268595c3056082ca769b5" + resolved "https://registry.npmjs.org/fastify-caching/-/fastify-caching-6.2.0.tgz" integrity sha512-JftadkAz/VvWiKqY98Kjmlp3o8ZiTOMmcd0P7XLzBiNmQdAX3mQR4s+YiEm0AWxDmmVaLVPfvuCne1AwbGtvPg== dependencies: abstract-cache "^1.0.1" @@ -4936,7 +4943,7 @@ fast-uri@^2.0.0, fast-uri@^2.1.0: fastify-caching@^6.3.0: version "6.3.0" - resolved "https://registry.yarnpkg.com/fastify-caching/-/fastify-caching-6.3.0.tgz#1d758cf89b71e9ee810ef68a9b3a6a78cea46d09" + resolved "https://registry.npmjs.org/fastify-caching/-/fastify-caching-6.3.0.tgz" integrity sha512-/oQZcaPuNXe6gv2wm5MNWGVATBD8yxSRX/SPM4zHQbxdJZpux/kDd9y6m47iG9dzrznN2sYkDHap836V0KveGw== dependencies: fastify-caching-deprecated "npm:fastify-caching@6.2.0" @@ -4967,7 +4974,7 @@ fastify-cli@^5.7.1: fastify-plugin@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-3.0.1.tgz#79e84c29f401020f38b524f59f2402103fd21ed2" + resolved "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.1.tgz" integrity sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA== fastify-plugin@^4.0.0, fastify-plugin@^4.5.0, fastify-plugin@~4.5.0: @@ -5017,7 +5024,7 @@ fb-watchman@^2.0.0: fetch-blob@^3.1.2, fetch-blob@^3.1.4: version "3.2.0" - resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz" integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== dependencies: node-domexception "^1.0.0" @@ -5160,7 +5167,7 @@ form-data@~2.3.2: formdata-polyfill@^4.0.10: version "4.0.10" - resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + resolved "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz" integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== dependencies: fetch-blob "^3.1.2" @@ -5500,7 +5507,7 @@ help-me@^4.0.1: help-me@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" + resolved "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz" integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== highlight.js@^10.7.1: @@ -5544,7 +5551,7 @@ http-signature@~1.3.6: https-proxy-agent@^7.0.4: version "7.0.5" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz" integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== dependencies: agent-base "^7.0.2" @@ -5600,7 +5607,7 @@ imurmurhash@^0.1.4: index-to-position@^0.1.2: version "0.1.2" - resolved "https://registry.yarnpkg.com/index-to-position/-/index-to-position-0.1.2.tgz#e11bfe995ca4d8eddb1ec43274488f3c201a7f09" + resolved "https://registry.npmjs.org/index-to-position/-/index-to-position-0.1.2.tgz" integrity sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g== inflight@^1.0.4: @@ -5627,12 +5634,12 @@ internal-slot@^1.0.7: inversify@^6.0.2: version "6.0.2" - resolved "https://registry.yarnpkg.com/inversify/-/inversify-6.0.2.tgz#dc7fa0348213d789d35ffb719dea9685570989c7" + resolved "https://registry.npmjs.org/inversify/-/inversify-6.0.2.tgz" integrity sha512-i9m8j/7YIv4mDuYXUAcrpKPSaju/CIly9AHK5jvCBeoiM/2KEsuCQTTP+rzSWWpLYWRukdXFSl6ZTk2/uumbiA== ioredis@^4.26.0: version "4.28.5" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.28.5.tgz#5c149e6a8d76a7f8fa8a504ffc85b7d5b6797f9f" + resolved "https://registry.npmjs.org/ioredis/-/ioredis-4.28.5.tgz" integrity sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A== dependencies: cluster-key-slot "^1.1.0" @@ -5649,7 +5656,7 @@ ioredis@^4.26.0: ioredis@^5.0.0, ioredis@^5.4.1: version "5.4.1" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.4.1.tgz#1c56b70b759f01465913887375ed809134296f40" + resolved "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz" integrity sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA== dependencies: "@ioredis/commands" "^1.1.1" @@ -5774,7 +5781,7 @@ is-number@^7.0.0: is-plain-obj@^1.1: version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== is-regex@^1.1.4: @@ -5864,7 +5871,7 @@ isexe@^2.0.0: isows@1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.4.tgz#810cd0d90cc4995c26395d2aa4cfa4037ebdf061" + resolved "https://registry.npmjs.org/isows/-/isows-1.0.4.tgz" integrity sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ== isstream@~0.1.2: @@ -6295,7 +6302,7 @@ joycon@^3.1.1: js-levenshtein@^1.1.6: version "1.1.6" - resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" + resolved "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz" integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== js-sha3@0.8.0, js-sha3@^0.8.0: @@ -6508,12 +6515,12 @@ lodash.debounce@^4.0.8: lodash.defaults@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + resolved "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz" integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== lodash.flatten@^4.4.0: version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + resolved "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz" integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== lodash.get@^4.4.2: @@ -6523,7 +6530,7 @@ lodash.get@^4.4.2: lodash.isarguments@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + resolved "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz" integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== lodash.isequal@^4.5.0: @@ -6562,7 +6569,7 @@ lru-cache@^6.0.0: lru_map@^0.3.3: version "0.3.3" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + resolved "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== make-dir@^3.0.0: @@ -6596,7 +6603,7 @@ media-typer@0.3.0: merge-options@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-1.0.1.tgz#2a64b24457becd4e4dc608283247e94ce589aa32" + resolved "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz" integrity sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg== dependencies: is-plain-obj "^1.1" @@ -6723,7 +6730,7 @@ muggle-string@^0.3.1: mustache@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" + resolved "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz" integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== mz@^2.4.0: @@ -6735,10 +6742,10 @@ mz@^2.4.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nanoid@^3.3.7: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== +nanoid@^3.3.8: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== natural-compare-lite@^1.4.0: version "1.4.0" @@ -6757,19 +6764,19 @@ node-addon-api@^3.2.1: node-cache@^5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d" + resolved "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz" integrity sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg== dependencies: clone "2.x" node-domexception@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== node-fetch@^2.6.1: version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" @@ -6783,7 +6790,7 @@ node-fetch@^2.6.12: node-fetch@^3.3.2: version "3.3.2" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz" integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== dependencies: data-uri-to-buffer "^4.0.0" @@ -6964,6 +6971,11 @@ obliterator@^2.0.1: resolved "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz" integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== +obuf@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + on-exit-leak-free@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz" @@ -6994,7 +7006,7 @@ open@^8.4.0: openapi-fetch@^0.10.2: version "0.10.2" - resolved "https://registry.yarnpkg.com/openapi-fetch/-/openapi-fetch-0.10.2.tgz#2c16bda62cf182ba780a9d94818294731de0b2d6" + resolved "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.10.2.tgz" integrity sha512-GCzgKIZchnxZRnztiOlRTKk9tQT0NHvs5MNXYFtOwG7xaj1iCJOGDsTLbn/2QUP37PjGTT890qERFjvmjxzQMg== dependencies: openapi-typescript-helpers "^0.0.9" @@ -7018,12 +7030,12 @@ openapi-typescript-helpers@^0.0.8: openapi-typescript-helpers@^0.0.9: version "0.0.9" - resolved "https://registry.yarnpkg.com/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.9.tgz#bb20cc0b79bf56d4a31a96477d7b2c8d33b9c836" + resolved "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.9.tgz" integrity sha512-BO2TvIDAO/FPVKz1Nj2gy+pUOHfaoENdK5UP3H0Jbh0VXBf3dwYMs58ZwOjiezrbHA2LamdquoyQgahTPvIxGA== openapi-typescript@^7.0.2: version "7.0.2" - resolved "https://registry.yarnpkg.com/openapi-typescript/-/openapi-typescript-7.0.2.tgz#9e50f8388dbeed87984f340149e6f853e5d77d0f" + resolved "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.0.2.tgz" integrity sha512-BBrYEf0YdW31Ernd07cD/qHoalSuiiUQvy+rHvU/1Iz9WbcFpRsIXrnfEnrEuiGTRuKCG6cDQCrxNK/rbwQRLg== dependencies: "@redocly/openapi-core" "^1.16.0" @@ -7074,7 +7086,7 @@ p-locate@^4.1.0: p-map@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + resolved "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== p-try@^2.0.0: @@ -7101,7 +7113,7 @@ parse-json@^5.0.0, parse-json@^5.2.0: parse-json@^8.1.0: version "8.1.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-8.1.0.tgz#91cdc7728004e955af9cb734de5684733b24a717" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-8.1.0.tgz" integrity sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA== dependencies: "@babel/code-frame" "^7.22.13" @@ -7167,7 +7179,7 @@ pg-cloudflare@^1.1.1: pg-connection-string@^2.7.0: version "2.7.0" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.7.0.tgz#f1d3489e427c62ece022dba98d5262efcb168b37" + resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz" integrity sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA== pg-int8@1.0.1: @@ -7175,15 +7187,20 @@ pg-int8@1.0.1: resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== -pg-pool@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.7.0.tgz#d4d3c7ad640f8c6a2245adc369bafde4ebb8cbec" - integrity sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g== +pg-numeric@1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz" + integrity sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw== -pg-protocol@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.7.0.tgz#ec037c87c20515372692edac8b63cf4405448a93" - integrity sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ== +pg-pool@^3.8.0: + version "3.8.0" + resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.8.0.tgz" + integrity sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw== + +pg-protocol@*, pg-protocol@^1.8.0: + version "1.8.0" + resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.8.0.tgz" + integrity sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g== pg-types@^2.1.0: version "2.2.0" @@ -7196,14 +7213,27 @@ pg-types@^2.1.0: postgres-date "~1.0.4" postgres-interval "^1.1.0" -pg@^8.13.1: - version "8.13.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-8.13.1.tgz#6498d8b0a87ff76c2df7a32160309d3168c0c080" - integrity sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ== +pg-types@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz" + integrity sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng== + dependencies: + pg-int8 "1.0.1" + pg-numeric "1.0.2" + postgres-array "~3.0.1" + postgres-bytea "~3.0.0" + postgres-date "~2.1.0" + postgres-interval "^3.0.0" + postgres-range "^1.1.1" + +pg@^8.14.1: + version "8.14.1" + resolved "https://registry.npmjs.org/pg/-/pg-8.14.1.tgz" + integrity sha512-0TdbqfjwIun9Fm/r89oB7RFQ0bLgduAhiIqIXOsyKoiC/L54DbuAAzIEN/9Op0f1Po9X7iCPXGoa/Ah+2aI8Xw== dependencies: pg-connection-string "^2.7.0" - pg-pool "^3.7.0" - pg-protocol "^1.7.0" + pg-pool "^3.8.0" + pg-protocol "^1.8.0" pg-types "^2.1.0" pgpass "1.x" optionalDependencies: @@ -7221,6 +7251,11 @@ picocolors@^1.0.0: resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" @@ -7236,7 +7271,7 @@ pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.0.0: pino-pretty@^11.2.2: version "11.2.2" - resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-11.2.2.tgz#5e8ec69b31e90eb187715af07b1d29a544e60d39" + resolved "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz" integrity sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A== dependencies: colorette "^2.0.7" @@ -7317,7 +7352,7 @@ pkg-up@^3.1.0: pluralize@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + resolved "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== possible-typed-array-names@^1.0.0: @@ -7326,29 +7361,46 @@ possible-typed-array-names@^1.0.0: integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== postcss@^8.4.27: - version "8.4.38" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" - integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== + version "8.5.3" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" + integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.2.0" + nanoid "^3.3.8" + picocolors "^1.1.1" + source-map-js "^1.2.1" postgres-array@~2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz" integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== +postgres-array@~3.0.1: + version "3.0.4" + resolved "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.4.tgz" + integrity sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ== + postgres-bytea@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz" integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== +postgres-bytea@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz" + integrity sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw== + dependencies: + obuf "~1.1.2" + postgres-date@~1.0.4: version "1.0.7" resolved "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz" integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== +postgres-date@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz" + integrity sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA== + postgres-interval@^1.1.0: version "1.2.0" resolved "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz" @@ -7356,6 +7408,16 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" +postgres-interval@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz" + integrity sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw== + +postgres-range@^1.1.1: + version "1.1.4" + resolved "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz" + integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" @@ -7382,7 +7444,7 @@ process-nextick-args@~2.0.0: process-warning@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" + resolved "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz" integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== process-warning@^2.0.0: @@ -7471,7 +7533,7 @@ quick-format-unescaped@^4.0.3: random-bytes@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" + resolved "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz" integrity sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ== react-is@^18.0.0: @@ -7536,17 +7598,17 @@ real-require@^0.2.0: redis-commands@1.7.0: version "1.7.0" - resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89" + resolved "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz" integrity sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ== redis-errors@^1.0.0, redis-errors@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" + resolved "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz" integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== redis-parser@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" + resolved "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz" integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== dependencies: redis-errors "^1.0.0" @@ -7563,7 +7625,7 @@ reflect-metadata@^0.1.13: reflect-metadata@^0.2.2: version "0.2.2" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" + resolved "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz" integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== regenerate-unicode-properties@^10.1.0: @@ -7728,9 +7790,9 @@ rollup@*: fsevents "~2.3.2" rollup@^3.27.1: - version "3.29.4" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" - integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw== + version "3.29.5" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.5.tgz#8a2e477a758b520fb78daf04bca4c522c1da8a54" + integrity sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w== optionalDependencies: fsevents "~2.3.2" @@ -7921,7 +7983,7 @@ sonic-boom@^3.0.0, sonic-boom@^3.1.0: sonic-boom@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.0.1.tgz#515b7cef2c9290cb362c4536388ddeece07aed30" + resolved "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz" integrity sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ== dependencies: atomic-sleep "^1.0.0" @@ -7931,10 +7993,10 @@ source-map-js@^1.0.2: resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -source-map-js@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== source-map-support@0.5.13: version "0.5.13" @@ -8003,7 +8065,7 @@ stack-utils@^2.0.3: standard-as-callback@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" + resolved "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz" integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== statuses@2.0.1: @@ -8154,7 +8216,7 @@ supports-color@^8.0.0, supports-color@^8.1.0: supports-color@^9.4.0: version "9.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.4.0.tgz#17bfcf686288f531db3dea3215510621ccb55954" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz" integrity sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw== supports-preserve-symlinks-flag@^1.0.0: @@ -8328,7 +8390,7 @@ ts-jest@^29.1.0: ts-node@10.9.1: version "10.9.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz" integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== dependencies: "@cspotcode/source-map-support" "^0.8.0" @@ -8412,7 +8474,7 @@ type-fest@^0.21.3: type-fest@^4.7.1: version "4.21.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.21.0.tgz#2eec399d9bda4ac686286314d07c6675fef3fdd8" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-4.21.0.tgz" integrity sha512-ADn2w7hVPcK6w1I0uWnM//y1rLXZhzB9mr0a3OirzclKF1Wp6VzevUmzz/NRAWunOT6E8HrnpGY7xOfc6K57fA== type-is@^1.6.18: @@ -8514,7 +8576,7 @@ typeorm@^0.3.11, typeorm@^0.3.17: typescript@^5.5.3: version "5.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.3.tgz#e1b0a3c394190838a0b168e771b0ad56a0af0faa" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz" integrity sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ== typescript@~5.0.4: @@ -8534,7 +8596,7 @@ typical@^5.2.0: uid-safe@^2.1.5: version "2.1.5" - resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" + resolved "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz" integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA== dependencies: random-bytes "~1.0.0" @@ -8677,7 +8739,7 @@ verror@1.10.0: viem@^2.18.4: version "2.18.4" - resolved "https://registry.yarnpkg.com/viem/-/viem-2.18.4.tgz#6af97b68141faa68f624b7cded4956065432a078" + resolved "https://registry.npmjs.org/viem/-/viem-2.18.4.tgz" integrity sha512-JGdN+PgBnZMbm7fc9o0SfHvL0CKyfrlhBUtaz27V+PeHO43Kgc9Zd4WyIbM8Brafq4TvVcnriRFW/FVGOzwEJw== dependencies: "@adraffy/ens-normalize" "1.10.0" @@ -8716,9 +8778,9 @@ vite-tsconfig-paths@^4.2.0: tsconfck "^2.1.0" vite@^4.3.9: - version "4.5.3" - resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.3.tgz#d88a4529ea58bae97294c7e2e6f0eab39a50fb1a" - integrity sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg== + version "4.5.12" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.12.tgz#48f48dbcf789722765e91bc32a99cb66c628eadc" + integrity sha512-qrMwavANtSz91nDy3zEiUHMtL09x0mniQsSMvDkNxuCBM1W5vriJ22hEmwTth6DhLSWsZnHBT0yHFAQXt6efGA== dependencies: esbuild "^0.18.10" postcss "^8.4.27" @@ -8752,12 +8814,12 @@ walker@^1.0.6, walker@^1.0.8: web-streams-polyfill@^3.0.3: version "3.3.3" - resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz" integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== webauthn-p256@0.0.5: version "0.0.5" - resolved "https://registry.yarnpkg.com/webauthn-p256/-/webauthn-p256-0.0.5.tgz#0baebd2ba8a414b21cc09c0d40f9dd0be96a06bd" + resolved "https://registry.npmjs.org/webauthn-p256/-/webauthn-p256-0.0.5.tgz" integrity sha512-drMGNWKdaixZNobeORVIqq7k5DsRC9FnG201K2QjeOoQLmtSDaSsVZdkg6n5jUALJKcAG++zBPJXmv6hy0nWFg== dependencies: "@noble/curves" "^1.4.0" @@ -8842,7 +8904,7 @@ ws@7.4.6: ws@8.17.1: version "8.17.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + resolved "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== ws@^8.4.2: @@ -8872,7 +8934,7 @@ yallist@^4.0.0: yaml-ast-parser@0.0.43: version "0.0.43" - resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb" + resolved "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz" integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A== yaml@^1.7.2: