From d6753eb1dbb4a5b00aa30081af7b61555d6d238e Mon Sep 17 00:00:00 2001 From: Gowtham Sundaresan <131300352+gowthamsundaresan@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:34:42 +0530 Subject: [PATCH 1/6] [Patch] - Requests sync to support instance scaling (#312) * fix: prevent strategy apy calculation leaking between Avs * move requests sync from cron to debounced manager * Revert "fix: prevent strategy apy calculation leaking between Avs" This reverts commit 8ce729fe2ffd0d19ec90db90b224e809d15240b4. --- packages/api/src/index.ts | 3 - packages/api/src/utils/authMiddleware.ts | 37 ++++-- packages/api/src/utils/request.ts | 3 +- .../api/src/utils/requestsUpdateManager.ts | 125 ++++++++++++++++++ packages/api/src/utils/userRequestsSync.ts | 93 ------------- 5 files changed, 151 insertions(+), 110 deletions(-) create mode 100644 packages/api/src/utils/requestsUpdateManager.ts delete mode 100644 packages/api/src/utils/userRequestsSync.ts diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 9c9a08d0..547fb009 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -8,7 +8,6 @@ import helmet from 'helmet' import cors from 'cors' import apiRouter from './routes' import { EigenExplorerApiError, handleAndReturnErrorResponse } from './schema/errors' -import { startUserRequestsSync } from './utils/userRequestsSync' const PORT = process.env.PORT ? Number.parseInt(process.env.PORT) : 3002 @@ -51,6 +50,4 @@ app.use((err: Error, req: Request, res: Response) => { // Start the server app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`) - - startUserRequestsSync() }) diff --git a/packages/api/src/utils/authMiddleware.ts b/packages/api/src/utils/authMiddleware.ts index cd4a7b4a..98d012df 100644 --- a/packages/api/src/utils/authMiddleware.ts +++ b/packages/api/src/utils/authMiddleware.ts @@ -3,6 +3,7 @@ import 'dotenv/config' import type { NextFunction, Request, Response } from 'express' import { authStore, requestsStore } from './authCache' import rateLimit from 'express-rate-limit' +import { triggerUserRequestsSync } from './requestsUpdateManager' // --- Types --- @@ -24,8 +25,7 @@ interface Plan { const PLANS: Record = { 0: { name: 'Unauthenticated', - requestsPerMin: 30, // Remove in v2 - requestsPerMonth: 1_000 // Remove in v2 + requestsPerMin: 10_000 // Remove in v2 }, 1: { name: 'Free', @@ -37,6 +37,10 @@ const PLANS: Record = { requestsPerMin: 1_000, requestsPerMonth: 10_000 }, + 998: { + name: 'Unknown', + requestsPerMin: 100_000 + }, 999: { name: 'Admin' } @@ -49,10 +53,11 @@ const PLANS: Record = { * Designed for speed over strictness, always giving user benefit of the doubt * * -1 -> Account restricted (monthly limit hit) - * 0 -> No API token (req will be blocked in v2) + * 0 -> Unauthenticated (req will be blocked in v2) * 1 -> Hobby plan or server/db error * 2 -> Basic plan - * 998 -> Fallback to db to in case auth store is updating (temp state, gets re-assigned to another value) + * 997 -> Fallback to db to in case auth store is updating (temp state, gets re-assigned to another value) + * 998 -> Unauthenticated and unknown IP. Since this can be multiple diff users, we set a higher rate limit (remove in v2) * 999 -> Admin access * * @param req @@ -64,10 +69,17 @@ export const authenticator = async (req: Request, res: Response, next: NextFunct const apiToken = req.header('X-API-Token') let accessLevel: number - // Find access level + // Find access level & set rate limiting key if (!apiToken) { - accessLevel = 0 + if (!req.ip) { + accessLevel = 998 + req.key = 'unknown' + } else { + accessLevel = 0 + req.key = req.ip + } } else { + req.key = apiToken const updatedAt: number | undefined = authStore.get('updatedAt') if (!updatedAt && !authStore.get('isRefreshing')) refreshAuthStore() @@ -76,14 +88,14 @@ export const authenticator = async (req: Request, res: Response, next: NextFunct if (process.env.EE_AUTH_TOKEN === apiToken) { accessLevel = 999 } else if (accountRestricted === 0) { - accessLevel = authStore.get(`apiToken:${apiToken}:accessLevel`) ?? 998 + accessLevel = authStore.get(`apiToken:${apiToken}:accessLevel`) ?? 997 } else { accessLevel = -1 } } // Handle limiting basis access level - if (accessLevel === 998) { + if (accessLevel === 997) { const response = await fetch(`${process.env.SUPABASE_FETCH_ACCESS_LEVEL_URL}/${apiToken}`, { method: 'GET', headers: { @@ -96,8 +108,7 @@ export const authenticator = async (req: Request, res: Response, next: NextFunct } // --- LIMITING TO BE ACTIVATED IN V2 --- - if (accessLevel === 0) accessLevel = 1 - if (accessLevel === -1) accessLevel = 1 + if (accessLevel === -1) accessLevel = 0 /* if (accessLevel === 0) { @@ -138,8 +149,7 @@ for (const [level, plan] of Object.entries(PLANS)) { max: plan.requestsPerMin, standardHeaders: true, legacyHeaders: false, - keyGenerator: (req: Request): string => - accessLevel === 0 ? req.ip ?? 'unknown' : req.header('X-API-Token') || '', + keyGenerator: (req: Request): string => req.key, message: `You've reached the limit of ${plan.requestsPerMin} requests per minute. ${ accessLevel === 0 ? 'Sign up for a plan on https://developer.eigenexplorer.com for increased limits.' @@ -157,7 +167,7 @@ for (const [level, plan] of Object.entries(PLANS)) { * @returns */ export const rateLimiter = (req: Request, res: Response, next: NextFunction) => { - const accessLevel = req.accessLevel || 0 + const accessLevel = req.accessLevel // No rate limiting for admin if (accessLevel === 999) { @@ -179,6 +189,7 @@ export const rateLimiter = (req: Request, res: Response, next: NextFunction) => const key = `apiToken:${apiToken}:newRequests` const currentCalls: number = requestsStore.get(key) || 0 requestsStore.set(key, currentCalls + 1) + triggerUserRequestsSync(apiToken) } } } catch {} diff --git a/packages/api/src/utils/request.ts b/packages/api/src/utils/request.ts index aed37e71..3d2421dc 100644 --- a/packages/api/src/utils/request.ts +++ b/packages/api/src/utils/request.ts @@ -3,7 +3,8 @@ import * as express from 'express' declare global { namespace Express { interface Request { - accessLevel?: number + accessLevel: number + key: string } } } diff --git a/packages/api/src/utils/requestsUpdateManager.ts b/packages/api/src/utils/requestsUpdateManager.ts new file mode 100644 index 00000000..a8b53dc4 --- /dev/null +++ b/packages/api/src/utils/requestsUpdateManager.ts @@ -0,0 +1,125 @@ +import { requestsStore } from './authCache' + +interface UpdatePayload { + key: string + data: { + apiToken: string + requests: number + } + timestamp: string +} + +interface QueueState { + current: Map + next: Map +} + +/** + * Manages DB updates for API Token request count + * + */ +class RequestsUpdateManager { + private updateInterval = 60_000 // 1 minute + private updateTimeout: NodeJS.Timeout | null = null + private queue: QueueState = { + current: new Map(), + next: new Map() + } + + constructor(private readonly supabaseUrl: string, private readonly supabaseKey: string) {} + + async queueUpdate(apiToken: string): Promise { + const requestKey = `apiToken:${apiToken}:newRequests` + const newRequests = Number(requestsStore.get(requestKey)) || 0 + + if (newRequests === 0) return + + const payload: UpdatePayload = { + key: apiToken, + data: { + apiToken, + requests: newRequests + }, + timestamp: new Date().toISOString() + } + + if (!this.updateTimeout) { + this.queue.current.set(apiToken, payload) + this.scheduleUpdate() + } else { + if (this.queue.current.size === 0) { + this.queue.next.set(apiToken, payload) + } else { + this.queue.current.set(apiToken, payload) + } + } + } + + private scheduleUpdate(): void { + if (this.updateTimeout) { + return + } + + this.updateTimeout = setTimeout(() => { + this.performUpdate() + }, this.updateInterval) + } + + private async performUpdate(): Promise { + try { + if (this.queue.current.size > 0) { + const updatePayload = Array.from(this.queue.current.values()) + await this.httpClient(this.supabaseUrl, updatePayload) + + // Clear processed requests from cache + for (const payload of updatePayload) { + const requestKey = `apiToken:${payload.data.apiToken}:newRequests` + requestsStore.del(requestKey) + } + + console.log(`[Data] User requests sync: size: ${updatePayload.length}`) + } + } catch (error) { + console.error('[Data] Update failed:', error) + } finally { + this.updateTimeout = null + this.queue.current = this.queue.next + this.queue.next = new Map() + + if (this.queue.current.size > 0) { + this.scheduleUpdate() + } + } + } + + private async httpClient(url: string, data: UpdatePayload[]): Promise { + const response = await fetch(url, { + method: 'POST', + headers: { + Authorization: `Bearer ${this.supabaseKey}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data.map((payload) => payload.data)) + }) + + if (!response.ok) { + throw new Error('Failed to post updates') + } + } +} + +const updateManager = new RequestsUpdateManager( + // biome-ignore lint/style/noNonNullAssertion: + process.env.SUPABASE_POST_REQUESTS_URL!, + // biome-ignore lint/style/noNonNullAssertion: + process.env.SUPABASE_SERVICE_ROLE_KEY! +) + +/** + * Call this function after a request is received & API Token is identified + * + * @returns + */ +export function triggerUserRequestsSync(apiToken: string) { + return updateManager.queueUpdate(apiToken) +} diff --git a/packages/api/src/utils/userRequestsSync.ts b/packages/api/src/utils/userRequestsSync.ts deleted file mode 100644 index 9e659794..00000000 --- a/packages/api/src/utils/userRequestsSync.ts +++ /dev/null @@ -1,93 +0,0 @@ -import type { User } from './authMiddleware' -import { requestsStore } from './authCache' -import cron from 'node-cron' - -/** - * Send updates to DB with number of requests in the past hour per user - * Cron job runs at the start of every hour - * - */ -export function startUserRequestsSync() { - cron.schedule('0 * * * *', async () => { - console.time('[Data] User requests sync') - - let isUpdateSuccess = true - let skip = 0 - const take = 10_000 - - while (true) { - try { - const getResponse = await fetch( - `${process.env.SUPABASE_FETCH_ALL_USERS_URL}?skip=${skip}&take=${take}`, - { - method: 'GET', - headers: { - Authorization: `Bearer ${process.env.SUPABASE_SERVICE_ROLE_KEY}`, - 'Content-Type': 'application/json' - } - } - ) - - if (!getResponse.ok) { - throw new Error() - } - - const users = (await getResponse.json()).data as User[] - - if (users.length === 0) break - - const updateList: { id: string; requests: number }[] = [] - for (const user of users) { - const apiTokens = user.apiTokens ?? [] - let totalNewRequests = 0 - - for (const apiToken of apiTokens) { - const key = `apiToken:${apiToken}:newRequests` - const newRequests = Number(requestsStore.get(key)) || 0 - if (newRequests > 0) totalNewRequests += newRequests - requestsStore.del(key) - } - - if (totalNewRequests > 0) { - updateList.push({ - id: user.id, - requests: user.requests + totalNewRequests - }) - } - } - - if (updateList.length > 0) { - const postResponse = await fetch(`${process.env.SUPABASE_POST_REQUESTS_URL}`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.SUPABASE_SERVICE_ROLE_KEY}`, - 'Content-Type': 'application/json' - }, - body: JSON.stringify(updateList) - }) - - if (!postResponse.ok) { - throw new Error() - } - - for (const user of users) { - const apiTokens = user.apiTokens ?? [] - - for (const apiToken of apiTokens) { - requestsStore.del(`apiToken:${apiToken}:newRequests`) - } - } - - console.log(`[Data] User requests sync: size: ${updateList.length}`) - } - } catch { - isUpdateSuccess = false - } - - skip += take - } - - if (isUpdateSuccess) requestsStore.flushAll() // Delete remaining (stale) keys once full update is successful - console.timeEnd('[Data] User requests sync') - }) -} From 14e97ff83a17f01c0ec14b6338dfaf45add9c15c Mon Sep 17 00:00:00 2001 From: Udit Veerwani <25996904+uditdc@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:35:02 +0530 Subject: [PATCH 2/6] fix: prevent strategy apy calculation leaking between Avs (#311) Co-authored-by: Gowtham S --- .../src/routes/operators/operatorController.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/api/src/routes/operators/operatorController.ts b/packages/api/src/routes/operators/operatorController.ts index d77bd1fc..88ff24b8 100644 --- a/packages/api/src/routes/operators/operatorController.ts +++ b/packages/api/src/routes/operators/operatorController.ts @@ -563,13 +563,6 @@ async function calculateOperatorApy(operator: any) { }[] } > = new Map() - const strategyApyMap: Map< - string, - { - apy: number - tokens: Map - } - > = new Map() const tokenPrices = await fetchTokenPrices() const strategiesWithSharesUnderlying = await getStrategiesWithShareUnderlying() @@ -592,6 +585,14 @@ async function calculateOperatorApy(operator: any) { return [] for (const avs of avsWithEligibleRewardSubmissions) { + const strategyApyMap: Map< + string, + { + apy: number + tokens: Map + } + > = new Map() + const shares = withOperatorShares(avs.avs.operators).filter( (s) => avs.avs.restakeableStrategies?.indexOf(s.strategyAddress.toLowerCase()) !== -1 ) From 95d7474c08e81d4de4db73b9ae9908be35a8eaea Mon Sep 17 00:00:00 2001 From: Surbhit Agrawal <82264758+surbhit14@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:38:13 +0530 Subject: [PATCH 3/6] Return empty response instead of error (#308) --- packages/api/src/routes/avs/avsController.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/api/src/routes/avs/avsController.ts b/packages/api/src/routes/avs/avsController.ts index eb1efb74..960e9cb6 100644 --- a/packages/api/src/routes/avs/avsController.ts +++ b/packages/api/src/routes/avs/avsController.ts @@ -528,12 +528,6 @@ export async function getAVSRewards(req: Request, res: Response) { } }) - if (!rewardsSubmissions || rewardsSubmissions.length === 0) { - throw new Error('AVS not found.') - } - - const tokenPrices = await fetchTokenPrices() - const result: { address: string submissions: Submission[] @@ -550,6 +544,11 @@ export async function getAVSRewards(req: Request, res: Response) { rewardStrategies: [] } + if (!rewardsSubmissions || rewardsSubmissions.length === 0) { + return res.send(result) + } + + const tokenPrices = await fetchTokenPrices() const rewardTokens: string[] = [] const rewardStrategies: string[] = [] let currentSubmission: Submission | null = null From 2be4d913cc0d69f1522452c74fff1a5969d395ea Mon Sep 17 00:00:00 2001 From: Gowtham Sundaresan <131300352+gowthamsundaresan@users.noreply.github.com> Date: Thu, 19 Dec 2024 20:05:46 +0530 Subject: [PATCH 4/6] [Patch] - Server auth optimizations (#314) * perf: remove extra fetch when pagination not required * chore: change refresh-store route from get to post --- packages/api/src/routes/auth/authController.ts | 2 +- packages/api/src/routes/auth/authRoutes.ts | 2 +- packages/api/src/utils/authMiddleware.ts | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/api/src/routes/auth/authController.ts b/packages/api/src/routes/auth/authController.ts index c66af47c..b4b0827b 100644 --- a/packages/api/src/routes/auth/authController.ts +++ b/packages/api/src/routes/auth/authController.ts @@ -152,7 +152,7 @@ export async function registerUser(req: Request, res: Response) { } /** - * Protected route, refreshes the server's entire auth store. Called by Supabase edge fn signal-refresh. + * Protected route, refreshes the server's entire auth store. Called by Supabase edge fn signal-refresh * This function will fail if the caller does not use admin-level auth token * * @param req diff --git a/packages/api/src/routes/auth/authRoutes.ts b/packages/api/src/routes/auth/authRoutes.ts index cfbddca4..8817e995 100644 --- a/packages/api/src/routes/auth/authRoutes.ts +++ b/packages/api/src/routes/auth/authRoutes.ts @@ -7,7 +7,7 @@ const router = express.Router() // API routes for /auth -router.get('/refresh-store', routeCache.cacheSeconds(5), signalRefreshAuthStore) +router.post('/refresh-store', signalRefreshAuthStore) router.get('/users/:address/check-status', routeCache.cacheSeconds(30), checkUserStatus) router.get('/users/:address/nonce', routeCache.cacheSeconds(10), generateNonce) router.post('/users/:address/register', routeCache.cacheSeconds(10), registerUser) diff --git a/packages/api/src/utils/authMiddleware.ts b/packages/api/src/utils/authMiddleware.ts index 98d012df..00fe9cbf 100644 --- a/packages/api/src/utils/authMiddleware.ts +++ b/packages/api/src/utils/authMiddleware.ts @@ -252,6 +252,9 @@ export async function refreshAuthStore() { ) } } + + if (users.length < take) break + skip += take } From c081c79a5a17a1e71278b860e8c317c0273dfc62 Mon Sep 17 00:00:00 2001 From: Surbhit Agrawal <82264758+surbhit14@users.noreply.github.com> Date: Thu, 19 Dec 2024 20:06:05 +0530 Subject: [PATCH 5/6] Update the example values (#313) --- .../src/schema/zod/schemas/eventSchemas.ts | 8 +- packages/openapi/openapi.json | 82 ++++++++++++------- .../operators/getOperatorDelegationEvents.ts | 2 +- .../getOperatorRegistrationEvents.ts | 2 +- .../stakers/getStakerDelegationEvents.ts | 2 +- .../routes/stakers/getStakerDepositEvents.ts | 2 +- .../stakers/getStakerWithdrawalEvents.ts | 2 +- 7 files changed, 65 insertions(+), 35 deletions(-) diff --git a/packages/api/src/schema/zod/schemas/eventSchemas.ts b/packages/api/src/schema/zod/schemas/eventSchemas.ts index c32c454e..a4fb1002 100644 --- a/packages/api/src/schema/zod/schemas/eventSchemas.ts +++ b/packages/api/src/schema/zod/schemas/eventSchemas.ts @@ -107,7 +107,10 @@ export const BaseEventQuerySchema = z.object({ message: 'Invalid date format for startAt. Use YYYY-MM-DD or ISO 8601 format.' } ) - .describe('Start date in ISO string format'), + .describe('Start date in ISO string format') + .openapi({ + example: '2024-11-15T00:00:00.000Z' + }), endAt: z .string() .optional() @@ -120,6 +123,9 @@ export const BaseEventQuerySchema = z.object({ } ) .describe('End date in ISO string format') + .openapi({ + example: '2024-12-15T00:00:00.000Z' + }) }) export const WithdrawalEventQuerySchemaBase = BaseEventQuerySchema.extend({ diff --git a/packages/openapi/openapi.json b/packages/openapi/openapi.json index 52a683d1..fe3529c0 100644 --- a/packages/openapi/openapi.json +++ b/packages/openapi/openapi.json @@ -4704,7 +4704,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -4713,7 +4714,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { @@ -4956,7 +4958,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -4965,7 +4968,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { @@ -6641,7 +6645,7 @@ "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "The address of the operator", - "example": "0x00107cfdeaddc0a3160ed2f6fedd627f313e7b1a" + "example": "0xDbEd88D83176316fc46797B43aDeE927Dc2ff2F5" }, "required": true }, @@ -6661,7 +6665,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -6670,7 +6675,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { @@ -6865,7 +6871,7 @@ "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "The address of the operator", - "example": "0x00107cfdeaddc0a3160ed2f6fedd627f313e7b1a" + "example": "0xDbEd88D83176316fc46797B43aDeE927Dc2ff2F5" }, "required": true }, @@ -6885,7 +6891,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -6894,7 +6901,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { @@ -8773,7 +8781,7 @@ "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "The address of the staker", - "example": "0x9791fdb4e9c0495efc5a1f3f9271ef226251eb34" + "example": "0xd4fcde9bb1d746Dd7e5463b01Dd819EE06aF25db" }, "required": true }, @@ -8793,7 +8801,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -8802,7 +8811,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { @@ -8997,7 +9007,7 @@ "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "The address of the staker", - "example": "0x9791fdb4e9c0495efc5a1f3f9271ef226251eb34" + "example": "0xd4fcde9bb1d746Dd7e5463b01Dd819EE06aF25db" }, "required": true }, @@ -9017,7 +9027,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -9026,7 +9037,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { @@ -9206,7 +9218,7 @@ "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "The address of the staker", - "example": "0x9791fdb4e9c0495efc5a1f3f9271ef226251eb34" + "example": "0xd4fcde9bb1d746Dd7e5463b01Dd819EE06aF25db" }, "required": true }, @@ -9226,7 +9238,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -9235,7 +9248,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { @@ -9720,7 +9734,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -9729,7 +9744,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { @@ -9927,7 +9943,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -9936,7 +9953,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { @@ -10173,7 +10191,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -10182,7 +10201,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { @@ -10375,7 +10395,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -10384,7 +10405,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { @@ -10626,7 +10648,8 @@ "description": "Start date in ISO string format", "schema": { "type": "string", - "description": "Start date in ISO string format" + "description": "Start date in ISO string format", + "example": "2024-11-15T00:00:00.000Z" } }, { @@ -10635,7 +10658,8 @@ "description": "End date in ISO string format", "schema": { "type": "string", - "description": "End date in ISO string format" + "description": "End date in ISO string format", + "example": "2024-12-15T00:00:00.000Z" } }, { diff --git a/packages/openapi/src/routes/operators/getOperatorDelegationEvents.ts b/packages/openapi/src/routes/operators/getOperatorDelegationEvents.ts index 9223f302..b4d1401d 100644 --- a/packages/openapi/src/routes/operators/getOperatorDelegationEvents.ts +++ b/packages/openapi/src/routes/operators/getOperatorDelegationEvents.ts @@ -14,7 +14,7 @@ import { applyAllRefinements } from '../../apiResponseSchema/events/util' const OperatorAddressParam = z.object({ address: EthereumAddressSchema.describe('The address of the operator').openapi({ - example: '0x00107cfdeaddc0a3160ed2f6fedd627f313e7b1a' + example: '0xDbEd88D83176316fc46797B43aDeE927Dc2ff2F5' }) }) diff --git a/packages/openapi/src/routes/operators/getOperatorRegistrationEvents.ts b/packages/openapi/src/routes/operators/getOperatorRegistrationEvents.ts index 7c89cdf3..b0b4fd25 100644 --- a/packages/openapi/src/routes/operators/getOperatorRegistrationEvents.ts +++ b/packages/openapi/src/routes/operators/getOperatorRegistrationEvents.ts @@ -12,7 +12,7 @@ import { applyAllRefinements } from '../../apiResponseSchema/events/util' const OperatorAddressParam = z.object({ address: EthereumAddressSchema.describe('The address of the operator').openapi({ - example: '0x00107cfdeaddc0a3160ed2f6fedd627f313e7b1a' + example: '0xDbEd88D83176316fc46797B43aDeE927Dc2ff2F5' }) }) diff --git a/packages/openapi/src/routes/stakers/getStakerDelegationEvents.ts b/packages/openapi/src/routes/stakers/getStakerDelegationEvents.ts index 553e930e..f4e05346 100644 --- a/packages/openapi/src/routes/stakers/getStakerDelegationEvents.ts +++ b/packages/openapi/src/routes/stakers/getStakerDelegationEvents.ts @@ -14,7 +14,7 @@ import { applyAllRefinements } from '../../apiResponseSchema/events/util' const StakerAddressParam = z.object({ address: EthereumAddressSchema.describe('The address of the staker').openapi({ - example: '0x9791fdb4e9c0495efc5a1f3f9271ef226251eb34' + example: '0xd4fcde9bb1d746Dd7e5463b01Dd819EE06aF25db' }) }) diff --git a/packages/openapi/src/routes/stakers/getStakerDepositEvents.ts b/packages/openapi/src/routes/stakers/getStakerDepositEvents.ts index 8e272747..abe6592c 100644 --- a/packages/openapi/src/routes/stakers/getStakerDepositEvents.ts +++ b/packages/openapi/src/routes/stakers/getStakerDepositEvents.ts @@ -13,7 +13,7 @@ import { applyAllRefinements } from '../../apiResponseSchema/events/util' const StakerAddressParam = z.object({ address: EthereumAddressSchema.describe('The address of the staker').openapi({ - example: '0x9791fdb4e9c0495efc5a1f3f9271ef226251eb34' + example: '0xd4fcde9bb1d746Dd7e5463b01Dd819EE06aF25db' }) }) diff --git a/packages/openapi/src/routes/stakers/getStakerWithdrawalEvents.ts b/packages/openapi/src/routes/stakers/getStakerWithdrawalEvents.ts index c9c0211b..1d4a4325 100644 --- a/packages/openapi/src/routes/stakers/getStakerWithdrawalEvents.ts +++ b/packages/openapi/src/routes/stakers/getStakerWithdrawalEvents.ts @@ -14,7 +14,7 @@ import { applyAllRefinements } from '../../apiResponseSchema/events/util' const StakerAddressParam = z.object({ address: EthereumAddressSchema.describe('The address of the staker').openapi({ - example: '0x9791fdb4e9c0495efc5a1f3f9271ef226251eb34' + example: '0xd4fcde9bb1d746Dd7e5463b01Dd819EE06aF25db' }) }) From e9ab19262a530d931107db9df03c9bda85b20d14 Mon Sep 17 00:00:00 2001 From: Udit Veerwani <25996904+uditdc@users.noreply.github.com> Date: Thu, 19 Dec 2024 20:08:32 +0530 Subject: [PATCH 6/6] hotfix: update column for sorting by apy (#315) Co-authored-by: Gowtham S --- packages/api/src/routes/avs/avsController.ts | 2 +- packages/api/src/routes/operators/operatorController.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/api/src/routes/avs/avsController.ts b/packages/api/src/routes/avs/avsController.ts index 960e9cb6..ee24b4b7 100644 --- a/packages/api/src/routes/avs/avsController.ts +++ b/packages/api/src/routes/avs/avsController.ts @@ -67,7 +67,7 @@ export async function getAllAVS(req: Request, res: Response) { : sortByTvl ? { field: 'tvlEth', order: sortByTvl } : sortByApy - ? { field: 'apy', order: sortByApy } + ? { field: 'maxApy', order: sortByApy } : null // Setup search query diff --git a/packages/api/src/routes/operators/operatorController.ts b/packages/api/src/routes/operators/operatorController.ts index 88ff24b8..c0468133 100644 --- a/packages/api/src/routes/operators/operatorController.ts +++ b/packages/api/src/routes/operators/operatorController.ts @@ -61,7 +61,7 @@ export async function getAllOperators(req: Request, res: Response) { : sortByTvl ? { field: 'tvlEth', order: sortByTvl } : sortByApy - ? { field: 'apy', order: sortByApy } + ? { field: 'maxApy', order: sortByApy } : null // Fetch records and apply search/sort