From 4326107e97496d0962eef8e35d2491161efa3103 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Tue, 21 May 2024 15:49:32 +0530 Subject: [PATCH 01/62] createdAtBlock & updatedAtBlock for avs, staker & operator --- packages/prisma/schema.prisma | 86 ++++++++++----------------- packages/seeder/src/seedAvs.ts | 84 +++++++++++++++++++------- packages/seeder/src/seedOperators.ts | 77 +++++++++++++++++------- packages/seeder/src/seedStakers.ts | 36 ++++++++--- packages/seeder/src/utils/metadata.ts | 10 ++++ 5 files changed, 189 insertions(+), 104 deletions(-) diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 340a1247..bcd2bd46 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -9,8 +9,7 @@ datasource db { } model Avs { - address String @id @unique - + address String @id @unique metadataName String metadataDescription String metadataDiscord String? @@ -18,15 +17,14 @@ model Avs { metadataTelegram String? metadataWebsite String? metadataX String? - - operators AvsOperator[] - curatedMetadata AvsCuratedMetadata? + createdAtBlock String? + updatedAtBlock String? + curatedMetadata AvsCuratedMetadata? + operators AvsOperator[] } model AvsCuratedMetadata { - avs Avs @relation(fields: [avsAddress], references: [address]) - avsAddress String @id @unique - + avsAddress String @id @unique metadataName String? metadataDescription String? metadataDiscord String? @@ -34,32 +32,31 @@ model AvsCuratedMetadata { metadataTelegram String? metadataWebsite String? metadataX String? - - tags String[] - isVisible Boolean @default(false) - isVerified Boolean @default(false) + tags String[] + isVisible Boolean @default(false) + isVerified Boolean @default(false) + avs Avs @relation(fields: [avsAddress], references: [address], map: "avscuratedmetadata_avsaddress_fkey") @@index([tags], map: "tags_1") } model AvsOperator { - avs Avs @relation(fields: [avsAddress], references: [address]) avsAddress String - operator Operator @relation(fields: [operatorAddress], references: [address]) operatorAddress String isActive Boolean + avs Avs @relation(fields: [avsAddress], references: [address], map: "avsoperator_avsaddress_fkey") + operator Operator @relation(fields: [operatorAddress], references: [address], map: "avsoperator_operatoraddress_fkey") @@id([avsAddress, operatorAddress]) } model Strategies { - address String @id + address String @id(map: "strategies_pkey") symbol String } model Operator { - address String @id @unique - + address String @id @unique metadataName String metadataDescription String metadataDiscord String? @@ -67,37 +64,38 @@ model Operator { metadataTelegram String? metadataWebsite String? metadataX String? - - avs AvsOperator[] - shares OperatorStrategyShares[] - stakers Staker[] + createdAtBlock String? + updatedAtBlock String? + avs AvsOperator[] + shares OperatorStrategyShares[] + stakers Staker[] } model OperatorStrategyShares { - Operator Operator @relation(fields: [operatorAddress], references: [address]) operatorAddress String strategyAddress String shares String + Operator Operator @relation(fields: [operatorAddress], references: [address], map: "operatorstrategyshares_operatoraddress_fkey") @@id([operatorAddress, strategyAddress]) } model Staker { - address String @id @unique - - operator Operator? @relation(fields: [operatorAddress], references: [address]) + address String @id(map: "staker_pkey") @unique operatorAddress String? - - shares StakerStrategyShares[] + createdAtBlock String? + updatedAtBlock String? + operator Operator? @relation(fields: [operatorAddress], references: [address], map: "staker_operatoraddress_fkey") + shares StakerStrategyShares[] } model StakerStrategyShares { - Staker Staker @relation(fields: [stakerAddress], references: [address]) stakerAddress String strategyAddress String shares String + Staker Staker @relation(fields: [stakerAddress], references: [address], map: "stakerstrategyshares_stakeraddress_fkey") - @@id([stakerAddress, strategyAddress]) + @@id([stakerAddress, strategyAddress], map: "stakerstrategyshares_pkey") } model Pod { @@ -111,39 +109,21 @@ model ValidatorRestake { validatorIndex BigInt blockNumber BigInt - @@id([podAddress, validatorIndex]) + @@id([podAddress, validatorIndex], map: "validatorrestake_pkey") } model Validator { - validatorIndex BigInt @id - status String - + validatorIndex BigInt @id(map: "validator_pkey") + status String balance BigInt effectiveBalance BigInt slashed Boolean withdrawalCredentials String } -model Withdrawal { - withdrawalRoot String @id @unique - nonce Int - isCompleted Boolean @default(false) - - stakerAddress String - delegatedTo String - withdrawerAddress String - strategies String[] - shares String[] - startBlock BigInt - - createdAtBlock BigInt - updatedAtBlock BigInt -} - -// Collection to store system settings model Settings { - key String @id @unique + key String @id(map: "settings_pkey") @unique value Json @db.Json - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + createdAt DateTime @default(now()) @db.Timestamp(6) + updatedAt DateTime @updatedAt @db.Timestamp(6) } diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 8f3e8875..25260cc2 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -1,6 +1,6 @@ import { parseAbiItem } from 'viem' import { isValidMetadataUrl, validateMetadata } from './utils/metadata' -import type { EntityMetadata } from './utils/metadata' +import { type EntityMetadata, defaultMetadata } from './utils/metadata' import { getEigenContracts } from './data/address' import { getViemClient } from './utils/viemClient' import { getPrismaClient } from './utils/prismaClient' @@ -25,7 +25,10 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const viemClient = getViemClient() const prismaClient = getPrismaClient() - const avsList: Map = new Map() + const avsList: Map< + string, + { metadata: EntityMetadata; createdAtBlock: string; updatedAtBlock: string } + > = new Map() const firstBlock = fromBlock ? fromBlock @@ -47,24 +50,46 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const log = logs[l] const avsAddress = String(log.args.avs).toLowerCase() - avsList.set(avsAddress, { - name: '', - website: '', - description: '', - logo: '', - x: '', - discord: '', - telegram: '' - }) - - if (log.args.metadataURI && isValidMetadataUrl(log.args.metadataURI)) { - const response = await fetch(log.args.metadataURI) - const data = await response.text() - const avsMetadata = validateMetadata(data) - - if (avsMetadata) { - avsList.set(avsAddress, avsMetadata) + const blockNumber = log.blockNumber.toString() + const existingRecord = avsList.get(avsAddress) + + try { + if (log.args.metadataURI && isValidMetadataUrl(log.args.metadataURI)) { + const response = await fetch(log.args.metadataURI) + const data = await response.text() + const avsMetadata = validateMetadata(data) + + if (avsMetadata) { + if (existingRecord) { + // Avs already registered, valid metadata uri + avsList.set(avsAddress, { + metadata: avsMetadata, + createdAtBlock: existingRecord.createdAtBlock, + updatedAtBlock: blockNumber + }) + } else { + // Avs not registered, valid metadata uri + avsList.set(avsAddress, { + metadata: avsMetadata, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber + }) + } + } else { + throw new Error('Missing avs metadata') + } + } else { + throw new Error('Invalid avs metadata uri') } + } catch (error) { + if (!existingRecord) { + // Avs not registered, invalid metadata uri + avsList.set(avsAddress, { + metadata: defaultMetadata, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber + }) + } // Ignore case where Avs is already registered and is updated with invalid metadata uri } } @@ -89,9 +114,14 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram?: string | null metadataWebsite?: string | null metadataX?: string | null + createdAtBlock: string + updatedAtBlock: string }[] = [] - for (const [address, metadata] of avsList) { + for (const [ + address, + { metadata, createdAtBlock, updatedAtBlock } + ] of avsList) { newAvs.push({ address, metadataName: metadata.name, @@ -101,6 +131,8 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, metadataX: metadata.x, + createdAtBlock: createdAtBlock, + updatedAtBlock: updatedAtBlock }) } @@ -111,7 +143,10 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { }) ) } else { - for (const [address, metadata] of avsList) { + for (const [ + address, + { metadata, createdAtBlock, updatedAtBlock } + ] of avsList) { dbTransactions.push( prismaClient.avs.upsert({ where: { address }, @@ -122,7 +157,8 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataDiscord: metadata.discord, metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, - metadataX: metadata.x + metadataX: metadata.x, + updatedAtBlock: updatedAtBlock }, create: { address, @@ -133,6 +169,8 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, metadataX: metadata.x, + createdAtBlock: createdAtBlock, + updatedAtBlock: updatedAtBlock } }) ) @@ -141,7 +179,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { await bulkUpdateDbTransactions(dbTransactions) - // Storing last sycned block + // Storing last synced block await saveLastSyncBlock(blockSyncKey, lastBlock) console.log('Seeded AVS:', avsList.size) diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index af77b307..e90e5478 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -1,7 +1,11 @@ import { getPrismaClient } from './utils/prismaClient' import { parseAbiItem } from 'viem' -import { isValidMetadataUrl, validateMetadata } from './utils/metadata' -import type { EntityMetadata } from './utils/metadata' +import { + type EntityMetadata, + defaultMetadata, + isValidMetadataUrl, + validateMetadata +} from './utils/metadata' import { getEigenContracts } from './data/address' import { getViemClient } from './utils/viemClient' import { @@ -19,7 +23,10 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const viemClient = getViemClient() const prismaClient = getPrismaClient() - const operatorList: Map = new Map() + const operatorList: Map< + string, + { metadata: EntityMetadata; createdAtBlock: string; updatedAtBlock: string } + > = new Map() const firstBlock = fromBlock ? fromBlock @@ -41,15 +48,31 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const log = logs[l] const operatorAddress = String(log.args.operator).toLowerCase() + const blockNumber = log.blockNumber.toString() + const existingRecord = operatorList.get(operatorAddress) try { if (log.args.metadataURI && isValidMetadataUrl(log.args.metadataURI)) { const response = await fetch(log.args.metadataURI) const data = await response.text() - const metadata = validateMetadata(data) - - if (metadata) { - operatorList.set(operatorAddress, metadata) + const operatorMetadata = validateMetadata(data) + + if (operatorMetadata) { + if (existingRecord) { + // Operator already registered, valid metadata uri + operatorList.set(operatorAddress, { + metadata: operatorMetadata, + createdAtBlock: existingRecord.createdAtBlock, + updatedAtBlock: blockNumber + }) + } else { + // Operator not registered, valid metadata uri + operatorList.set(operatorAddress, { + metadata: operatorMetadata, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber + }) + } } else { throw new Error('Missing operator metadata') } @@ -57,15 +80,14 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { throw new Error('Invalid operator metadata uri') } } catch (error) { - operatorList.set(operatorAddress, { - name: '', - description: '', - discord: '', - logo: '', - telegram: '', - website: '', - x: '' - }) + if (!existingRecord) { + // Operator not registered, invalid metadata uri + operatorList.set(operatorAddress, { + metadata: defaultMetadata, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber + }) + } // Ignore case where Operator is already registered and is updated with invalid metadata uri } } @@ -90,9 +112,14 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram?: string | null metadataWebsite?: string | null metadataX?: string | null + createdAtBlock: string + updatedAtBlock: string }[] = [] - for (const [address, metadata] of operatorList) { + for (const [ + address, + { metadata, createdAtBlock, updatedAtBlock } + ] of operatorList) { newOperator.push({ address, metadataName: metadata.name, @@ -101,7 +128,9 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataDiscord: metadata.discord, metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, - metadataX: metadata.x + metadataX: metadata.x, + createdAtBlock: createdAtBlock, + updatedAtBlock: updatedAtBlock }) } @@ -112,7 +141,10 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { }) ) } else { - for (const [address, metadata] of operatorList) { + for (const [ + address, + { metadata, createdAtBlock, updatedAtBlock } + ] of operatorList) { dbTransactions.push( prismaClient.operator.upsert({ where: { address }, @@ -123,7 +155,8 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataDiscord: metadata.discord, metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, - metadataX: metadata.x + metadataX: metadata.x, + updatedAtBlock: updatedAtBlock }, create: { address, @@ -133,7 +166,9 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataDiscord: metadata.discord, metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, - metadataX: metadata.x + metadataX: metadata.x, + createdAtBlock: createdAtBlock, + updatedAtBlock: updatedAtBlock } }) ) diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index be6966e2..9dfe6c52 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -3,10 +3,10 @@ import { getEigenContracts } from './data/address' import { getViemClient } from './utils/viemClient' import { getPrismaClient } from './utils/prismaClient' import { + type IMap, baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, - IMap, loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -23,6 +23,8 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { { operatorAddress: string | null shares: { shares: bigint; strategyAddress: string }[] + createdAtBlock: string + updatedAtBlock: string } > = new Map() @@ -70,6 +72,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { for (const l in logs) { const log = logs[l] + const blockNumber = log.blockNumber.toString() const operatorAddress = String(log.args.operator).toLowerCase() const stakerAddress = String(log.args.staker).toLowerCase() @@ -79,19 +82,28 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { (s) => s.address.toLowerCase() === stakerAddress.toLowerCase() ) if (foundStakerInit) { + // Address not in this set of logs but in db stakers.set(stakerAddress, { operatorAddress: foundStakerInit.operatorAddress, shares: foundStakerInit.shares.map((s) => ({ ...s, shares: BigInt(s.shares) - })) + })), + createdAtBlock: foundStakerInit.createdAtBlock, + updatedAtBlock: blockNumber }) } else { + // Address neither in this set of logs nor in db stakers.set(stakerAddress, { operatorAddress: null, - shares: [] + shares: [], + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber }) } + } else { + // Address previously found in this set of logs + stakers.get(stakerAddress).updatedAtBlock = blockNumber } if (log.eventName === 'StakerDelegated') { @@ -150,7 +162,12 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { dbTransactions.push(prismaClient.stakerStrategyShares.deleteMany()) dbTransactions.push(prismaClient.staker.deleteMany()) - const newStakers: { address: string; operatorAddress: string | null }[] = [] + const newStakers: { + address: string + operatorAddress: string | null + createdAtBlock: string + updatedAtBlock: string + }[] = [] const newStakerShares: { stakerAddress: string strategyAddress: string @@ -160,7 +177,9 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { for (const [stakerAddress, stakerDetails] of stakers) { newStakers.push({ address: stakerAddress, - operatorAddress: stakerDetails.operatorAddress + operatorAddress: stakerDetails.operatorAddress, + createdAtBlock: stakerDetails.createdAtBlock, + updatedAtBlock: stakerDetails.updatedAtBlock }) stakerDetails.shares.map((share) => { @@ -192,10 +211,13 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { where: { address: stakerAddress }, create: { address: stakerAddress, - operatorAddress: stakerDetails.operatorAddress + operatorAddress: stakerDetails.operatorAddress, + createdAtBlock: stakerDetails.createdAtBlock, + updatedAtBlock: stakerDetails.updatedAtBlock }, update: { - operatorAddress: stakerDetails.operatorAddress + operatorAddress: stakerDetails.operatorAddress, + updatedAtBlock: stakerDetails.updatedAtBlock } }) ) diff --git a/packages/seeder/src/utils/metadata.ts b/packages/seeder/src/utils/metadata.ts index 4bbe6159..259405a0 100644 --- a/packages/seeder/src/utils/metadata.ts +++ b/packages/seeder/src/utils/metadata.ts @@ -8,6 +8,16 @@ export interface EntityMetadata { x: string } +export const defaultMetadata: EntityMetadata = { + name: '', + website: '', + description: '', + logo: '', + x: '', + discord: '', + telegram: '' +} + export function isValidMetadataUrl(url: string): boolean { // Define the regular expression pattern for HTTPS URLs const httpsUrlPattern = From 7962ab2e3e1da5988f6da9bcd4cbd6a1a44466b3 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Tue, 21 May 2024 16:41:38 +0530 Subject: [PATCH 02/62] Revert schema.prisma updates to version on file --- packages/prisma/schema.prisma | 100 ++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 34 deletions(-) diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index bcd2bd46..ff17df00 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -9,7 +9,8 @@ datasource db { } model Avs { - address String @id @unique + address String @id @unique + metadataName String metadataDescription String metadataDiscord String? @@ -17,14 +18,18 @@ model Avs { metadataTelegram String? metadataWebsite String? metadataX String? - createdAtBlock String? - updatedAtBlock String? - curatedMetadata AvsCuratedMetadata? - operators AvsOperator[] + + operators AvsOperator[] + curatedMetadata AvsCuratedMetadata? + + createdAtBlock BigInt + updatedAtBlock BigInt } model AvsCuratedMetadata { - avsAddress String @id @unique + avs Avs @relation(fields: [avsAddress], references: [address]) + avsAddress String @id @unique + metadataName String? metadataDescription String? metadataDiscord String? @@ -32,31 +37,32 @@ model AvsCuratedMetadata { metadataTelegram String? metadataWebsite String? metadataX String? - tags String[] - isVisible Boolean @default(false) - isVerified Boolean @default(false) - avs Avs @relation(fields: [avsAddress], references: [address], map: "avscuratedmetadata_avsaddress_fkey") + + tags String[] + isVisible Boolean @default(false) + isVerified Boolean @default(false) @@index([tags], map: "tags_1") } model AvsOperator { + avs Avs @relation(fields: [avsAddress], references: [address]) avsAddress String + operator Operator @relation(fields: [operatorAddress], references: [address]) operatorAddress String isActive Boolean - avs Avs @relation(fields: [avsAddress], references: [address], map: "avsoperator_avsaddress_fkey") - operator Operator @relation(fields: [operatorAddress], references: [address], map: "avsoperator_operatoraddress_fkey") @@id([avsAddress, operatorAddress]) } model Strategies { - address String @id(map: "strategies_pkey") + address String @id symbol String } model Operator { - address String @id @unique + address String @id @unique + metadataName String metadataDescription String metadataDiscord String? @@ -64,44 +70,52 @@ model Operator { metadataTelegram String? metadataWebsite String? metadataX String? - createdAtBlock String? - updatedAtBlock String? - avs AvsOperator[] - shares OperatorStrategyShares[] - stakers Staker[] + + avs AvsOperator[] + shares OperatorStrategyShares[] + stakers Staker[] + + createdAtBlock BigInt + updatedAtBlock BigInt } model OperatorStrategyShares { + Operator Operator @relation(fields: [operatorAddress], references: [address]) operatorAddress String strategyAddress String shares String - Operator Operator @relation(fields: [operatorAddress], references: [address], map: "operatorstrategyshares_operatoraddress_fkey") @@id([operatorAddress, strategyAddress]) } model Staker { - address String @id(map: "staker_pkey") @unique + address String @id @unique + + operator Operator? @relation(fields: [operatorAddress], references: [address]) operatorAddress String? - createdAtBlock String? - updatedAtBlock String? - operator Operator? @relation(fields: [operatorAddress], references: [address], map: "staker_operatoraddress_fkey") - shares StakerStrategyShares[] + + shares StakerStrategyShares[] + + createdAtBlock BigInt + updatedAtBlock BigInt } model StakerStrategyShares { + Staker Staker @relation(fields: [stakerAddress], references: [address]) stakerAddress String strategyAddress String shares String - Staker Staker @relation(fields: [stakerAddress], references: [address], map: "stakerstrategyshares_stakeraddress_fkey") - @@id([stakerAddress, strategyAddress], map: "stakerstrategyshares_pkey") + @@id([stakerAddress, strategyAddress]) } model Pod { address String @id @unique owner String - blockNumber BigInt + blockNumber BigInt // @Deprecated, will remove in future release + + createdAtBlock BigInt + updatedAtBlock BigInt } model ValidatorRestake { @@ -109,21 +123,39 @@ model ValidatorRestake { validatorIndex BigInt blockNumber BigInt - @@id([podAddress, validatorIndex], map: "validatorrestake_pkey") + @@id([podAddress, validatorIndex]) } model Validator { - validatorIndex BigInt @id(map: "validator_pkey") - status String + validatorIndex BigInt @id + status String + balance BigInt effectiveBalance BigInt slashed Boolean withdrawalCredentials String } +model Withdrawal { + withdrawalRoot String @id @unique + nonce Int + isCompleted Boolean @default(false) + + stakerAddress String + delegatedTo String + withdrawerAddress String + strategies String[] + shares String[] + startBlock BigInt + + createdAtBlock BigInt + updatedAtBlock BigInt +} + +// Collection to store system settings model Settings { - key String @id(map: "settings_pkey") @unique + key String @id @unique value Json @db.Json - createdAt DateTime @default(now()) @db.Timestamp(6) - updatedAt DateTime @updatedAt @db.Timestamp(6) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } From 986a494b5a40785677e85e88839e9418ac542052 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Wed, 22 May 2024 18:15:30 +0530 Subject: [PATCH 03/62] changed blocknumber type to bigint --- packages/seeder/src/seedAvs.ts | 8 ++++---- packages/seeder/src/seedOperators.ts | 8 ++++---- packages/seeder/src/seedStakers.ts | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 25260cc2..81234ffc 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -27,7 +27,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const prismaClient = getPrismaClient() const avsList: Map< string, - { metadata: EntityMetadata; createdAtBlock: string; updatedAtBlock: string } + { metadata: EntityMetadata; createdAtBlock: bigint; updatedAtBlock: bigint } > = new Map() const firstBlock = fromBlock @@ -50,7 +50,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const log = logs[l] const avsAddress = String(log.args.avs).toLowerCase() - const blockNumber = log.blockNumber.toString() + const blockNumber = BigInt(log.blockNumber) const existingRecord = avsList.get(avsAddress) try { @@ -114,8 +114,8 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram?: string | null metadataWebsite?: string | null metadataX?: string | null - createdAtBlock: string - updatedAtBlock: string + createdAtBlock: bigint + updatedAtBlock: bigint }[] = [] for (const [ diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index e90e5478..05cb2f1c 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -25,7 +25,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const prismaClient = getPrismaClient() const operatorList: Map< string, - { metadata: EntityMetadata; createdAtBlock: string; updatedAtBlock: string } + { metadata: EntityMetadata; createdAtBlock: bigint; updatedAtBlock: bigint } > = new Map() const firstBlock = fromBlock @@ -48,7 +48,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const log = logs[l] const operatorAddress = String(log.args.operator).toLowerCase() - const blockNumber = log.blockNumber.toString() + const blockNumber = BigInt(log.blockNumber) const existingRecord = operatorList.get(operatorAddress) try { @@ -112,8 +112,8 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram?: string | null metadataWebsite?: string | null metadataX?: string | null - createdAtBlock: string - updatedAtBlock: string + createdAtBlock: bigint + updatedAtBlock: bigint }[] = [] for (const [ diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index 9dfe6c52..3bbd0463 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -23,8 +23,8 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { { operatorAddress: string | null shares: { shares: bigint; strategyAddress: string }[] - createdAtBlock: string - updatedAtBlock: string + createdAtBlock: bigint + updatedAtBlock: bigint } > = new Map() @@ -72,7 +72,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { for (const l in logs) { const log = logs[l] - const blockNumber = log.blockNumber.toString() + const blockNumber = BigInt(log.blockNumber) const operatorAddress = String(log.args.operator).toLowerCase() const stakerAddress = String(log.args.staker).toLowerCase() @@ -165,8 +165,8 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { const newStakers: { address: string operatorAddress: string | null - createdAtBlock: string - updatedAtBlock: string + createdAtBlock: bigint + updatedAtBlock: bigint }[] = [] const newStakerShares: { stakerAddress: string From d798ba8f9609cd52a25809a870d87cf6ed16c722 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Thu, 23 May 2024 03:43:14 +0530 Subject: [PATCH 04/62] Include block number default, create migration --- .../migration.sql | 19 ++++++++++++++++++ packages/prisma/schema.prisma | 20 +++++++++---------- 2 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 packages/prisma/migrations/20240522221237_include_created_update_block/migration.sql diff --git a/packages/prisma/migrations/20240522221237_include_created_update_block/migration.sql b/packages/prisma/migrations/20240522221237_include_created_update_block/migration.sql new file mode 100644 index 00000000..c60dd73b --- /dev/null +++ b/packages/prisma/migrations/20240522221237_include_created_update_block/migration.sql @@ -0,0 +1,19 @@ +-- AlterTable +ALTER TABLE "Avs" ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, +ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Operator" ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, +ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Pod" ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, +ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Staker" ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, +ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Withdrawal" ALTER COLUMN "createdAtBlock" SET DEFAULT 0, +ALTER COLUMN "updatedAtBlock" SET DEFAULT 0; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index ff17df00..fb631bb5 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -22,8 +22,8 @@ model Avs { operators AvsOperator[] curatedMetadata AvsCuratedMetadata? - createdAtBlock BigInt - updatedAtBlock BigInt + createdAtBlock BigInt @default(0) + updatedAtBlock BigInt @default(0) } model AvsCuratedMetadata { @@ -75,8 +75,8 @@ model Operator { shares OperatorStrategyShares[] stakers Staker[] - createdAtBlock BigInt - updatedAtBlock BigInt + createdAtBlock BigInt @default(0) + updatedAtBlock BigInt @default(0) } model OperatorStrategyShares { @@ -96,8 +96,8 @@ model Staker { shares StakerStrategyShares[] - createdAtBlock BigInt - updatedAtBlock BigInt + createdAtBlock BigInt @default(0) + updatedAtBlock BigInt @default(0) } model StakerStrategyShares { @@ -114,8 +114,8 @@ model Pod { owner String blockNumber BigInt // @Deprecated, will remove in future release - createdAtBlock BigInt - updatedAtBlock BigInt + createdAtBlock BigInt @default(0) + updatedAtBlock BigInt @default(0) } model ValidatorRestake { @@ -148,8 +148,8 @@ model Withdrawal { shares String[] startBlock BigInt - createdAtBlock BigInt - updatedAtBlock BigInt + createdAtBlock BigInt @default(0) + updatedAtBlock BigInt @default(0) } // Collection to store system settings From 3742621e48cb49f2d28303e9ddb6d64692b7c151 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Thu, 23 May 2024 14:28:27 +0530 Subject: [PATCH 05/62] added createdAt & updatedAt for avs, operator & staker --- packages/seeder/src/seedAvs.ts | 42 +++++++++++++++++++++------- packages/seeder/src/seedOperators.ts | 42 +++++++++++++++++++++------- packages/seeder/src/seedStakers.ts | 29 +++++++++++++++---- 3 files changed, 87 insertions(+), 26 deletions(-) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 81234ffc..3924d617 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -27,7 +27,13 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const prismaClient = getPrismaClient() const avsList: Map< string, - { metadata: EntityMetadata; createdAtBlock: bigint; updatedAtBlock: bigint } + { + metadata: EntityMetadata + createdAtBlock: bigint + updatedAtBlock: bigint + createdAt: Date + updatedAt: Date + } > = new Map() const firstBlock = fromBlock @@ -50,9 +56,12 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const log = logs[l] const avsAddress = String(log.args.avs).toLowerCase() - const blockNumber = BigInt(log.blockNumber) const existingRecord = avsList.get(avsAddress) + const blockNumber = BigInt(log.blockNumber) + const block = await viemClient.getBlock({ blockNumber: blockNumber }) + const timestamp = new Date(Number(block.timestamp) * 1000) + try { if (log.args.metadataURI && isValidMetadataUrl(log.args.metadataURI)) { const response = await fetch(log.args.metadataURI) @@ -65,14 +74,18 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { avsList.set(avsAddress, { metadata: avsMetadata, createdAtBlock: existingRecord.createdAtBlock, - updatedAtBlock: blockNumber + updatedAtBlock: blockNumber, + createdAt: existingRecord.createdAt, + updatedAt: timestamp }) } else { // Avs not registered, valid metadata uri avsList.set(avsAddress, { metadata: avsMetadata, createdAtBlock: blockNumber, - updatedAtBlock: blockNumber + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp }) } } else { @@ -87,7 +100,9 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { avsList.set(avsAddress, { metadata: defaultMetadata, createdAtBlock: blockNumber, - updatedAtBlock: blockNumber + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp }) } // Ignore case where Avs is already registered and is updated with invalid metadata uri } @@ -116,11 +131,13 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataX?: string | null createdAtBlock: bigint updatedAtBlock: bigint + createdAt: Date + updatedAt: Date }[] = [] for (const [ address, - { metadata, createdAtBlock, updatedAtBlock } + { metadata, createdAtBlock, updatedAtBlock, createdAt, updatedAt } ] of avsList) { newAvs.push({ address, @@ -132,7 +149,9 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataWebsite: metadata.website, metadataX: metadata.x, createdAtBlock: createdAtBlock, - updatedAtBlock: updatedAtBlock + updatedAtBlock: updatedAtBlock, + createdAt: createdAt, + updatedAt: updatedAt }) } @@ -145,7 +164,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { } else { for (const [ address, - { metadata, createdAtBlock, updatedAtBlock } + { metadata, createdAtBlock, updatedAtBlock, createdAt, updatedAt } ] of avsList) { dbTransactions.push( prismaClient.avs.upsert({ @@ -158,7 +177,8 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, metadataX: metadata.x, - updatedAtBlock: updatedAtBlock + updatedAtBlock: updatedAtBlock, + updatedAt: updatedAt }, create: { address, @@ -170,7 +190,9 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataWebsite: metadata.website, metadataX: metadata.x, createdAtBlock: createdAtBlock, - updatedAtBlock: updatedAtBlock + updatedAtBlock: updatedAtBlock, + createdAt: createdAt, + updatedAt: updatedAt } }) ) diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index 05cb2f1c..903f480c 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -25,7 +25,13 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const prismaClient = getPrismaClient() const operatorList: Map< string, - { metadata: EntityMetadata; createdAtBlock: bigint; updatedAtBlock: bigint } + { + metadata: EntityMetadata + createdAtBlock: bigint + updatedAtBlock: bigint + createdAt: Date + updatedAt: Date + } > = new Map() const firstBlock = fromBlock @@ -48,9 +54,12 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const log = logs[l] const operatorAddress = String(log.args.operator).toLowerCase() - const blockNumber = BigInt(log.blockNumber) const existingRecord = operatorList.get(operatorAddress) + const blockNumber = BigInt(log.blockNumber) + const block = await viemClient.getBlock({ blockNumber: blockNumber }) + const timestamp = new Date(Number(block.timestamp) * 1000) + try { if (log.args.metadataURI && isValidMetadataUrl(log.args.metadataURI)) { const response = await fetch(log.args.metadataURI) @@ -63,14 +72,18 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { operatorList.set(operatorAddress, { metadata: operatorMetadata, createdAtBlock: existingRecord.createdAtBlock, - updatedAtBlock: blockNumber + updatedAtBlock: blockNumber, + createdAt: existingRecord.createdAt, + updatedAt: timestamp }) } else { // Operator not registered, valid metadata uri operatorList.set(operatorAddress, { metadata: operatorMetadata, createdAtBlock: blockNumber, - updatedAtBlock: blockNumber + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp }) } } else { @@ -85,7 +98,9 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { operatorList.set(operatorAddress, { metadata: defaultMetadata, createdAtBlock: blockNumber, - updatedAtBlock: blockNumber + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp }) } // Ignore case where Operator is already registered and is updated with invalid metadata uri } @@ -114,11 +129,13 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataX?: string | null createdAtBlock: bigint updatedAtBlock: bigint + createdAt: Date + updatedAt: Date }[] = [] for (const [ address, - { metadata, createdAtBlock, updatedAtBlock } + { metadata, createdAtBlock, updatedAtBlock, createdAt, updatedAt } ] of operatorList) { newOperator.push({ address, @@ -130,7 +147,9 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataWebsite: metadata.website, metadataX: metadata.x, createdAtBlock: createdAtBlock, - updatedAtBlock: updatedAtBlock + updatedAtBlock: updatedAtBlock, + createdAt: createdAt, + updatedAt: updatedAt }) } @@ -143,7 +162,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { } else { for (const [ address, - { metadata, createdAtBlock, updatedAtBlock } + { metadata, createdAtBlock, updatedAtBlock, createdAt, updatedAt } ] of operatorList) { dbTransactions.push( prismaClient.operator.upsert({ @@ -156,7 +175,8 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, metadataX: metadata.x, - updatedAtBlock: updatedAtBlock + updatedAtBlock: updatedAtBlock, + updatedAt: updatedAt }, create: { address, @@ -168,7 +188,9 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataWebsite: metadata.website, metadataX: metadata.x, createdAtBlock: createdAtBlock, - updatedAtBlock: updatedAtBlock + updatedAtBlock: updatedAtBlock, + createdAt: createdAt, + updatedAt: updatedAt } }) ) diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index 3bbd0463..5ffd621e 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -25,6 +25,8 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { shares: { shares: bigint; strategyAddress: string }[] createdAtBlock: bigint updatedAtBlock: bigint + createdAt: Date + updatedAt: Date } > = new Map() @@ -72,10 +74,13 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { for (const l in logs) { const log = logs[l] - const blockNumber = BigInt(log.blockNumber) const operatorAddress = String(log.args.operator).toLowerCase() const stakerAddress = String(log.args.staker).toLowerCase() + const blockNumber = BigInt(log.blockNumber) + const block = await viemClient.getBlock({ blockNumber: blockNumber }) + const timestamp = new Date(Number(block.timestamp) * 1000) + // Load existing staker shares data if (!stakers.has(stakerAddress)) { const foundStakerInit = stakerInit.find( @@ -90,7 +95,9 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { shares: BigInt(s.shares) })), createdAtBlock: foundStakerInit.createdAtBlock, - updatedAtBlock: blockNumber + updatedAtBlock: blockNumber, + createdAt: foundStakerInit.createdAt, + updatedAt: timestamp }) } else { // Address neither in this set of logs nor in db @@ -98,12 +105,15 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { operatorAddress: null, shares: [], createdAtBlock: blockNumber, - updatedAtBlock: blockNumber + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp }) } } else { // Address previously found in this set of logs stakers.get(stakerAddress).updatedAtBlock = blockNumber + stakers.get(stakerAddress).updatedAt = timestamp } if (log.eventName === 'StakerDelegated') { @@ -167,6 +177,8 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { operatorAddress: string | null createdAtBlock: bigint updatedAtBlock: bigint + createdAt: Date + updatedAt: Date }[] = [] const newStakerShares: { stakerAddress: string @@ -179,7 +191,9 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { address: stakerAddress, operatorAddress: stakerDetails.operatorAddress, createdAtBlock: stakerDetails.createdAtBlock, - updatedAtBlock: stakerDetails.updatedAtBlock + updatedAtBlock: stakerDetails.updatedAtBlock, + createdAt: stakerDetails.createdAt, + updatedAt: stakerDetails.updatedAt }) stakerDetails.shares.map((share) => { @@ -213,11 +227,14 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { address: stakerAddress, operatorAddress: stakerDetails.operatorAddress, createdAtBlock: stakerDetails.createdAtBlock, - updatedAtBlock: stakerDetails.updatedAtBlock + updatedAtBlock: stakerDetails.updatedAtBlock, + createdAt: stakerDetails.createdAt, + updatedAt: stakerDetails.updatedAt }, update: { operatorAddress: stakerDetails.operatorAddress, - updatedAtBlock: stakerDetails.updatedAtBlock + updatedAtBlock: stakerDetails.updatedAtBlock, + updatedAt: stakerDetails.updatedAt } }) ) From 874cf3f6903dc48830ee36de285ebbffeca699d3 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Thu, 23 May 2024 15:29:49 +0530 Subject: [PATCH 06/62] updated prisma.schema with createdAt & updatedAt for avs, staker and operator --- packages/prisma/schema.prisma | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index fb631bb5..76af704b 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -24,6 +24,8 @@ model Avs { createdAtBlock BigInt @default(0) updatedAtBlock BigInt @default(0) + createdAt DateTime? @db.Timestamptz(6) + updatedAt DateTime? @db.Timestamptz(6) } model AvsCuratedMetadata { @@ -77,6 +79,8 @@ model Operator { createdAtBlock BigInt @default(0) updatedAtBlock BigInt @default(0) + createdAt DateTime? @db.Timestamptz(6) + updatedAt DateTime? @db.Timestamptz(6) } model OperatorStrategyShares { @@ -98,6 +102,8 @@ model Staker { createdAtBlock BigInt @default(0) updatedAtBlock BigInt @default(0) + createdAt DateTime? @db.Timestamptz(6) + updatedAt DateTime? @db.Timestamptz(6) } model StakerStrategyShares { From ae4902982369e3c8da3c52d4ef45102223862b3a Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Thu, 23 May 2024 17:51:59 +0530 Subject: [PATCH 07/62] Include updated migrations --- .../migration.sql | 19 ---------- .../migration.sql | 29 +++++++++++++++ packages/prisma/schema.prisma | 36 ++++++++++--------- 3 files changed, 49 insertions(+), 35 deletions(-) delete mode 100644 packages/prisma/migrations/20240522221237_include_created_update_block/migration.sql create mode 100644 packages/prisma/migrations/20240523121211_include_created_updated_block_ts/migration.sql diff --git a/packages/prisma/migrations/20240522221237_include_created_update_block/migration.sql b/packages/prisma/migrations/20240522221237_include_created_update_block/migration.sql deleted file mode 100644 index c60dd73b..00000000 --- a/packages/prisma/migrations/20240522221237_include_created_update_block/migration.sql +++ /dev/null @@ -1,19 +0,0 @@ --- AlterTable -ALTER TABLE "Avs" ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, -ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "Operator" ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, -ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "Pod" ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, -ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "Staker" ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, -ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "Withdrawal" ALTER COLUMN "createdAtBlock" SET DEFAULT 0, -ALTER COLUMN "updatedAtBlock" SET DEFAULT 0; diff --git a/packages/prisma/migrations/20240523121211_include_created_updated_block_ts/migration.sql b/packages/prisma/migrations/20240523121211_include_created_updated_block_ts/migration.sql new file mode 100644 index 00000000..4b86e5dc --- /dev/null +++ b/packages/prisma/migrations/20240523121211_include_created_updated_block_ts/migration.sql @@ -0,0 +1,29 @@ +-- AlterTable +ALTER TABLE "Avs" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Operator" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Pod" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Staker" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "createdAtBlock" BIGINT NOT NULL DEFAULT 0, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "updatedAtBlock" BIGINT NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Withdrawal" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ALTER COLUMN "createdAtBlock" SET DEFAULT 0, +ALTER COLUMN "updatedAtBlock" SET DEFAULT 0; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 76af704b..884ad847 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -22,10 +22,10 @@ model Avs { operators AvsOperator[] curatedMetadata AvsCuratedMetadata? - createdAtBlock BigInt @default(0) - updatedAtBlock BigInt @default(0) - createdAt DateTime? @db.Timestamptz(6) - updatedAt DateTime? @db.Timestamptz(6) + createdAtBlock BigInt @default(0) + updatedAtBlock BigInt @default(0) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) } model AvsCuratedMetadata { @@ -77,10 +77,10 @@ model Operator { shares OperatorStrategyShares[] stakers Staker[] - createdAtBlock BigInt @default(0) - updatedAtBlock BigInt @default(0) - createdAt DateTime? @db.Timestamptz(6) - updatedAt DateTime? @db.Timestamptz(6) + createdAtBlock BigInt @default(0) + updatedAtBlock BigInt @default(0) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) } model OperatorStrategyShares { @@ -100,10 +100,10 @@ model Staker { shares StakerStrategyShares[] - createdAtBlock BigInt @default(0) - updatedAtBlock BigInt @default(0) - createdAt DateTime? @db.Timestamptz(6) - updatedAt DateTime? @db.Timestamptz(6) + createdAtBlock BigInt @default(0) + updatedAtBlock BigInt @default(0) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) } model StakerStrategyShares { @@ -120,8 +120,10 @@ model Pod { owner String blockNumber BigInt // @Deprecated, will remove in future release - createdAtBlock BigInt @default(0) - updatedAtBlock BigInt @default(0) + createdAtBlock BigInt @default(0) + updatedAtBlock BigInt @default(0) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) } model ValidatorRestake { @@ -154,8 +156,10 @@ model Withdrawal { shares String[] startBlock BigInt - createdAtBlock BigInt @default(0) - updatedAtBlock BigInt @default(0) + createdAtBlock BigInt @default(0) + updatedAtBlock BigInt @default(0) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) } // Collection to store system settings From 412f12f901fbd2a8d1cd5a1a1208dd622dbbf31a Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Thu, 23 May 2024 19:23:06 +0530 Subject: [PATCH 08/62] Include created, updated fields on Pods and Withdrawals --- packages/seeder/src/seedAvs.ts | 35 ++++++------------ packages/seeder/src/seedOperators.ts | 35 ++++++------------ packages/seeder/src/seedPods.ts | 23 +++++++++--- packages/seeder/src/seedStakers.ts | 37 +++++++------------- packages/seeder/src/seedWithdrawalsQueued.ts | 15 +++++--- 5 files changed, 65 insertions(+), 80 deletions(-) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 3924d617..f258fdf0 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -1,3 +1,4 @@ +import prisma from '@prisma/client' import { parseAbiItem } from 'viem' import { isValidMetadataUrl, validateMetadata } from './utils/metadata' import { type EntityMetadata, defaultMetadata } from './utils/metadata' @@ -14,6 +15,14 @@ import { const blockSyncKey = 'lastSyncedBlock_avs' +interface AvsEntryRecord { + metadata: EntityMetadata + createdAtBlock: bigint + updatedAtBlock: bigint + createdAt: Date + updatedAt: Date +} + /** * Utility function to seed avs * @@ -25,16 +34,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const viemClient = getViemClient() const prismaClient = getPrismaClient() - const avsList: Map< - string, - { - metadata: EntityMetadata - createdAtBlock: bigint - updatedAtBlock: bigint - createdAt: Date - updatedAt: Date - } - > = new Map() + const avsList: Map = new Map() const firstBlock = fromBlock ? fromBlock @@ -120,20 +120,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { if (firstBlock === baseBlock) { dbTransactions.push(prismaClient.avs.deleteMany()) - const newAvs: { - address: string - metadataName: string - metadataDescription: string - metadataDiscord?: string | null - metadataLogo?: string | null - metadataTelegram?: string | null - metadataWebsite?: string | null - metadataX?: string | null - createdAtBlock: bigint - updatedAtBlock: bigint - createdAt: Date - updatedAt: Date - }[] = [] + const newAvs: prisma.Avs[] = [] for (const [ address, diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index 903f480c..eac606fb 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -1,3 +1,4 @@ +import prisma from '@prisma/client' import { getPrismaClient } from './utils/prismaClient' import { parseAbiItem } from 'viem' import { @@ -18,21 +19,20 @@ import { const blockSyncKey = 'lastSyncedBlock_operators' +interface OperatorEntryRecord { + metadata: EntityMetadata + createdAtBlock: bigint + updatedAtBlock: bigint + createdAt: Date + updatedAt: Date +} + export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { console.log('Seeding Operators ...') const viemClient = getViemClient() const prismaClient = getPrismaClient() - const operatorList: Map< - string, - { - metadata: EntityMetadata - createdAtBlock: bigint - updatedAtBlock: bigint - createdAt: Date - updatedAt: Date - } - > = new Map() + const operatorList: Map = new Map() const firstBlock = fromBlock ? fromBlock @@ -118,20 +118,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { if (firstBlock === baseBlock) { dbTransactions.push(prismaClient.operator.deleteMany()) - const newOperator: { - address: string - metadataName: string - metadataDescription: string - metadataDiscord?: string | null - metadataLogo?: string | null - metadataTelegram?: string | null - metadataWebsite?: string | null - metadataX?: string | null - createdAtBlock: bigint - updatedAtBlock: bigint - createdAt: Date - updatedAt: Date - }[] = [] + const newOperator: prisma.Operator[] = [] for (const [ address, diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index 82d2c93f..e438f639 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -1,3 +1,4 @@ +import prisma from '@prisma/client' import { parseAbiItem } from 'viem' import { getEigenContracts } from './data/address' import { getViemClient } from './utils/viemClient' @@ -22,7 +23,7 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { const viemClient = getViemClient() const prismaClient = getPrismaClient() - const podList: { address: string; owner: string; blockNumber: bigint }[] = [] + const podList: prisma.Pod[] = [] const firstBlock = fromBlock ? fromBlock @@ -46,10 +47,18 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { const podAddress = String(log.args.eigenPod).toLowerCase() const podOwner = String(log.args.podOwner).toLowerCase() + const blockNumber = BigInt(log.blockNumber) + const block = await viemClient.getBlock({ blockNumber: blockNumber }) + const timestamp = new Date(Number(block.timestamp) * 1000) + podList.push({ address: podAddress, owner: podOwner, - blockNumber: log.blockNumber + blockNumber, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp }) } @@ -79,12 +88,18 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { where: { address: pod.address }, update: { owner: pod.owner, - blockNumber: pod.blockNumber + blockNumber: pod.blockNumber, + updatedAtBlock: pod.updatedAtBlock, + updatedAt: pod.updatedAt }, create: { address: pod.address, owner: pod.owner, - blockNumber: pod.blockNumber + blockNumber: pod.blockNumber, + createdAtBlock: pod.createdAtBlock, + createdAt: pod.createdAt, + updatedAtBlock: pod.updatedAtBlock, + updatedAt: pod.updatedAt } }) ) diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index 5ffd621e..ec14aad6 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -1,3 +1,4 @@ +import prisma from '@prisma/client' import { parseAbiItem } from 'viem' import { getEigenContracts } from './data/address' import { getViemClient } from './utils/viemClient' @@ -13,22 +14,21 @@ import { const blockSyncKey = 'lastSyncedBlock_stakers' +interface StakerEntryRecord { + operatorAddress: string | null + shares: { shares: bigint; strategyAddress: string }[] + createdAtBlock: bigint + updatedAtBlock: bigint + createdAt: Date + updatedAt: Date +} + export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { console.log('Seeding stakers ...') const viemClient = getViemClient() const prismaClient = getPrismaClient() - const stakers: IMap< - string, - { - operatorAddress: string | null - shares: { shares: bigint; strategyAddress: string }[] - createdAtBlock: bigint - updatedAtBlock: bigint - createdAt: Date - updatedAt: Date - } - > = new Map() + const stakers: IMap = new Map() const firstBlock = fromBlock ? fromBlock @@ -172,19 +172,8 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { dbTransactions.push(prismaClient.stakerStrategyShares.deleteMany()) dbTransactions.push(prismaClient.staker.deleteMany()) - const newStakers: { - address: string - operatorAddress: string | null - createdAtBlock: bigint - updatedAtBlock: bigint - createdAt: Date - updatedAt: Date - }[] = [] - const newStakerShares: { - stakerAddress: string - strategyAddress: string - shares: string - }[] = [] + const newStakers: prisma.Staker[] = [] + const newStakerShares: prisma.StakerStrategyShares[] = [] for (const [stakerAddress, stakerDetails] of stakers) { newStakers.push({ diff --git a/packages/seeder/src/seedWithdrawalsQueued.ts b/packages/seeder/src/seedWithdrawalsQueued.ts index 718dd417..00f13450 100644 --- a/packages/seeder/src/seedWithdrawalsQueued.ts +++ b/packages/seeder/src/seedWithdrawalsQueued.ts @@ -1,3 +1,4 @@ +import prisma from '@prisma/client' import { parseAbiItem } from 'viem' import { getEigenContracts } from './data/address' import { getViemClient } from './utils/viemClient' @@ -40,7 +41,7 @@ export async function seedQueuedWithdrawals( const viemClient = getViemClient() const prismaClient = getPrismaClient() - const queuedWithdrawalList: Withdrawal[] = [] + const queuedWithdrawalList: prisma.Withdrawal[] = [] const firstBlock = fromBlock ? fromBlock @@ -65,6 +66,10 @@ export async function seedQueuedWithdrawals( const withdrawalRoot = log.args.withdrawalRoot const withdrawal = log.args.withdrawal + const blockNumber = BigInt(log.blockNumber) + const block = await viemClient.getBlock({ blockNumber: blockNumber }) + const timestamp = new Date(Number(block.timestamp) * 1000) + if (withdrawalRoot && withdrawal) { const stakerAddress = withdrawal.staker.toLowerCase() const delegatedTo = withdrawal.delegatedTo.toLowerCase() @@ -81,10 +86,12 @@ export async function seedQueuedWithdrawals( s.toLowerCase() ) as string[], shares: withdrawal.shares.map((s) => BigInt(s).toString()), - startBlock: withdrawal.startBlock, - createdAtBlock: Number(log.blockNumber), - updatedAtBlock: Number(log.blockNumber) + startBlock: BigInt(withdrawal.startBlock), + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp }) } } From 28df8be512d4ec731254431e8d8ead93c9faa007 Mon Sep 17 00:00:00 2001 From: Liam Zhang Date: Thu, 23 May 2024 21:03:19 -0700 Subject: [PATCH 09/62] withdrawal api --- packages/openapi/openapi.json | 1344 ++++++++++++++++- .../src/apiResponseSchema/operatorResponse.ts | 32 - .../withdrawals/withdrawalsResponseSchema.ts | 58 + packages/openapi/src/documentBase.ts | 4 + packages/openapi/src/routes/avs/getAllAvs.ts | 4 +- .../routes/avs/getAvsOperatorsByAddress.ts | 4 +- .../src/routes/operators/getAllOperators.ts | 4 +- .../routes/operators/getOperatorByAddress.ts | 2 +- .../stakers/getCompletedStakerWithdrawals.ts | 40 + .../stakers/getQueuedStakerWithdrawals.ts | 39 + .../getQueuedWithdrawableStakerWithdrawals.ts | 42 + .../routes/stakers/getStakerWithdrawals.ts | 40 + packages/openapi/src/routes/stakers/index.ts | 20 + .../routes/withdrawals/getAllWithdrawals.ts | 39 + .../getWithdralByWithdrawalRoot.ts | 35 + .../openapi/src/routes/withdrawals/index.ts | 12 + 16 files changed, 1633 insertions(+), 86 deletions(-) create mode 100644 packages/openapi/src/apiResponseSchema/withdrawals/withdrawalsResponseSchema.ts create mode 100644 packages/openapi/src/routes/stakers/getCompletedStakerWithdrawals.ts create mode 100644 packages/openapi/src/routes/stakers/getQueuedStakerWithdrawals.ts create mode 100644 packages/openapi/src/routes/stakers/getQueuedWithdrawableStakerWithdrawals.ts create mode 100644 packages/openapi/src/routes/stakers/getStakerWithdrawals.ts create mode 100644 packages/openapi/src/routes/stakers/index.ts create mode 100644 packages/openapi/src/routes/withdrawals/getAllWithdrawals.ts create mode 100644 packages/openapi/src/routes/withdrawals/getWithdralByWithdrawalRoot.ts create mode 100644 packages/openapi/src/routes/withdrawals/index.ts diff --git a/packages/openapi/openapi.json b/packages/openapi/openapi.json index 83e8b590..f5135eb3 100644 --- a/packages/openapi/openapi.json +++ b/packages/openapi/openapi.json @@ -520,6 +520,21 @@ "AVS" ], "parameters": [ + { + "in": "query", + "name": "withTvl", + "description": "Toggle whether the route should calculate the TVL from shares", + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ], + "default": "false", + "description": "Toggle whether the route should calculate the TVL from shares", + "example": "false" + } + }, { "in": "query", "name": "skip", @@ -541,21 +556,6 @@ "description": "The number of records to return for pagination", "example": 12 } - }, - { - "in": "query", - "name": "withTvl", - "description": "Toggle whether the route should calculate the TVL from shares", - "schema": { - "type": "string", - "enum": [ - "true", - "false" - ], - "default": "false", - "description": "Toggle whether the route should calculate the TVL from shares", - "example": "false" - } } ], "responses": { @@ -1360,6 +1360,21 @@ }, "required": true }, + { + "in": "query", + "name": "withTvl", + "description": "Toggle whether the route should calculate the TVL from shares", + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ], + "default": "false", + "description": "Toggle whether the route should calculate the TVL from shares", + "example": "false" + } + }, { "in": "query", "name": "skip", @@ -1381,21 +1396,6 @@ "description": "The number of records to return for pagination", "example": 12 } - }, - { - "in": "query", - "name": "withTvl", - "description": "Toggle whether the route should calculate the TVL from shares", - "schema": { - "type": "string", - "enum": [ - "true", - "false" - ], - "default": "false", - "description": "Toggle whether the route should calculate the TVL from shares", - "example": "false" - } } ], "responses": { @@ -1639,6 +1639,21 @@ "Operators" ], "parameters": [ + { + "in": "query", + "name": "withTvl", + "description": "Toggle whether the route should calculate the TVL from shares", + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ], + "default": "false", + "description": "Toggle whether the route should calculate the TVL from shares", + "example": "false" + } + }, { "in": "query", "name": "skip", @@ -1660,21 +1675,6 @@ "description": "The number of records to return for pagination", "example": 12 } - }, - { - "in": "query", - "name": "withTvl", - "description": "Toggle whether the route should calculate the TVL from shares", - "schema": { - "type": "string", - "enum": [ - "true", - "false" - ], - "default": "false", - "description": "Toggle whether the route should calculate the TVL from shares", - "example": "false" - } } ], "responses": { @@ -1921,11 +1921,11 @@ { "in": "path", "name": "address", - "description": "The address of the operator.", + "description": "The address of the operator", "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", - "description": "The address of the operator.", + "description": "The address of the operator", "example": "0x00107cfdeaddc0a3160ed2f6fedd627f313e7b1b" }, "required": true @@ -2140,6 +2140,1256 @@ } } } + }, + "/withdrawals": { + "get": { + "operationId": "getAllWithdrawals", + "summary": "Retrieve all withdrawals", + "description": "Returns all withdrawal data, including the withdrawal root, nonce, withdrawal status, and other relevant information.", + "tags": [ + "Withdrawals" + ], + "parameters": [ + { + "in": "query", + "name": "stakerAddress", + "description": "The address of the staker", + "schema": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + } + }, + { + "in": "query", + "name": "delegatedTo", + "description": "The address of the operator to which the stake is delegated", + "schema": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the operator to which the stake is delegated", + "example": "0x5accc90436492f24e6af278569691e2c942a676d" + } + }, + { + "in": "query", + "name": "strategyAddress", + "description": "The contract address of the restaking strategy", + "schema": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the restaking strategy", + "example": "0x0fe4f44bee93503346a3ac9ee5a26b130a5796d6" + } + }, + { + "in": "query", + "name": "status", + "description": "The status of the withdrawal", + "schema": { + "type": "string", + "enum": [ + "queued", + "queued_withdrawable", + "completed" + ], + "description": "The status of the withdrawal", + "example": "queued" + } + }, + { + "in": "query", + "name": "skip", + "description": "The number of records to skip for pagination", + "schema": { + "type": "string", + "default": "0", + "description": "The number of records to skip for pagination", + "example": 0 + } + }, + { + "in": "query", + "name": "take", + "description": "The number of records to return for pagination", + "schema": { + "type": "string", + "default": "12", + "description": "The number of records to return for pagination", + "example": 12 + } + } + ], + "responses": { + "200": { + "description": "The list of withdrawals.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "withdrawalRoot": { + "type": "string", + "description": "The root hash of the withdrawal", + "example": "0x9e6728ef0a8ad6009107a886047aae35bc5ed7deaa68580b0d1f8f67e3e5ed31" + }, + "nonce": { + "type": "number", + "description": "The nonce of the withdrawal", + "example": 0 + }, + "isCompleted": { + "type": "boolean", + "description": "Indicates if the withdrawal is completed", + "example": false + }, + "stakerAddress": { + "type": "string", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "delegatedTo": { + "type": "string", + "description": "The operator address to which staking is delegated", + "example": "0x0000000000000000000000000000000000000000" + }, + "withdrawerAddress": { + "type": "string", + "description": "The address of the withdrawer", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "shares": { + "type": "array", + "items": { + "type": "object", + "properties": { + "strategyAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the restaking strategy", + "example": "0xbeac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0" + }, + "shares": { + "type": "string", + "description": "The amount of shares held in the strategy", + "example": "1277920000000000000000000" + } + }, + "required": [ + "strategyAddress", + "shares" + ] + }, + "description": "The list of strategy shares", + "example": [ + { + "strategyAddress": "0x93c4b944d05dfe6df7645a86cd2206016c51564d", + "shares": "1000288824523326631" + } + ] + }, + "startBlock": { + "type": "number", + "description": "The block number when the withdrawal was queued", + "example": 19912470 + }, + "createdAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was recorded by EigenExplorer", + "example": 19912470 + }, + "updatedAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was last updated", + "example": 19912470 + } + }, + "required": [ + "withdrawalRoot", + "nonce", + "isCompleted", + "stakerAddress", + "delegatedTo", + "withdrawerAddress", + "shares", + "startBlock", + "createdAtBlock", + "updatedAtBlock" + ] + } + }, + "meta": { + "type": "object", + "properties": { + "total": { + "type": "number", + "description": "Total number of records in the database", + "example": 30 + }, + "skip": { + "type": "number", + "description": "The number of skiped records for this query", + "example": 0 + }, + "take": { + "type": "number", + "description": "The number of records returned for this query", + "example": 12 + } + }, + "required": [ + "total", + "skip", + "take" + ] + } + }, + "required": [ + "data", + "meta" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/400" + }, + "401": { + "$ref": "#/components/responses/401" + }, + "403": { + "$ref": "#/components/responses/403" + }, + "404": { + "$ref": "#/components/responses/404" + }, + "422": { + "$ref": "#/components/responses/422" + }, + "429": { + "$ref": "#/components/responses/429" + }, + "500": { + "$ref": "#/components/responses/500" + } + } + } + }, + "/withdrawals/{withdrawalRoot}": { + "get": { + "operationId": "getWithdrawalByWithdrawalRoot", + "summary": "Retrieve withdrawal by withdrawal root", + "description": "Returns the withdrawal data by withdrawal root.", + "tags": [ + "Withdrawals" + ], + "parameters": [ + { + "in": "path", + "name": "withdrawalRoot", + "description": "The root hash of the withdrawal", + "schema": { + "type": "string", + "description": "The root hash of the withdrawal", + "example": "0x9e6728ef0a8ad6009107a886047aae35bc5ed7deaa68580b0d1f8f67e3e5ed31" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The requested withdrawal record.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "withdrawalRoot": { + "type": "string", + "description": "The root hash of the withdrawal", + "example": "0x9e6728ef0a8ad6009107a886047aae35bc5ed7deaa68580b0d1f8f67e3e5ed31" + }, + "nonce": { + "type": "number", + "description": "The nonce of the withdrawal", + "example": 0 + }, + "isCompleted": { + "type": "boolean", + "description": "Indicates if the withdrawal is completed", + "example": false + }, + "stakerAddress": { + "type": "string", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "delegatedTo": { + "type": "string", + "description": "The operator address to which staking is delegated", + "example": "0x0000000000000000000000000000000000000000" + }, + "withdrawerAddress": { + "type": "string", + "description": "The address of the withdrawer", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "shares": { + "type": "array", + "items": { + "type": "object", + "properties": { + "strategyAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the restaking strategy", + "example": "0xbeac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0" + }, + "shares": { + "type": "string", + "description": "The amount of shares held in the strategy", + "example": "1277920000000000000000000" + } + }, + "required": [ + "strategyAddress", + "shares" + ] + }, + "description": "The list of strategy shares", + "example": [ + { + "strategyAddress": "0x93c4b944d05dfe6df7645a86cd2206016c51564d", + "shares": "1000288824523326631" + } + ] + }, + "startBlock": { + "type": "number", + "description": "The block number when the withdrawal was queued", + "example": 19912470 + }, + "createdAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was recorded by EigenExplorer", + "example": 19912470 + }, + "updatedAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was last updated", + "example": 19912470 + } + }, + "required": [ + "withdrawalRoot", + "nonce", + "isCompleted", + "stakerAddress", + "delegatedTo", + "withdrawerAddress", + "shares", + "startBlock", + "createdAtBlock", + "updatedAtBlock" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/400" + }, + "401": { + "$ref": "#/components/responses/401" + }, + "403": { + "$ref": "#/components/responses/403" + }, + "404": { + "$ref": "#/components/responses/404" + }, + "422": { + "$ref": "#/components/responses/422" + }, + "429": { + "$ref": "#/components/responses/429" + }, + "500": { + "$ref": "#/components/responses/500" + } + } + } + }, + "/stakers/{address}/withdrawals": { + "get": { + "operationId": "getStakerWithdrawals", + "summary": "Retrieve all withdrawals by staker address", + "description": "Returns all withdrawal data of the requested staker, including the withdrawal root, nonce, withdrawal status, and other relevant information.", + "tags": [ + "Stakers" + ], + "parameters": [ + { + "in": "path", + "name": "address", + "description": "The address of the staker", + "schema": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "required": true + }, + { + "in": "query", + "name": "total", + "description": "Total number of records in the database", + "schema": { + "type": "number", + "description": "Total number of records in the database", + "example": 30 + }, + "required": true + }, + { + "in": "query", + "name": "skip", + "description": "The number of skiped records for this query", + "schema": { + "type": "number", + "description": "The number of skiped records for this query", + "example": 0 + }, + "required": true + }, + { + "in": "query", + "name": "take", + "description": "The number of records returned for this query", + "schema": { + "type": "number", + "description": "The number of records returned for this query", + "example": 12 + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The list of withdrawals.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "withdrawalRoot": { + "type": "string", + "description": "The root hash of the withdrawal", + "example": "0x9e6728ef0a8ad6009107a886047aae35bc5ed7deaa68580b0d1f8f67e3e5ed31" + }, + "nonce": { + "type": "number", + "description": "The nonce of the withdrawal", + "example": 0 + }, + "isCompleted": { + "type": "boolean", + "description": "Indicates if the withdrawal is completed", + "example": false + }, + "stakerAddress": { + "type": "string", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "delegatedTo": { + "type": "string", + "description": "The operator address to which staking is delegated", + "example": "0x0000000000000000000000000000000000000000" + }, + "withdrawerAddress": { + "type": "string", + "description": "The address of the withdrawer", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "shares": { + "type": "array", + "items": { + "type": "object", + "properties": { + "strategyAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the restaking strategy", + "example": "0xbeac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0" + }, + "shares": { + "type": "string", + "description": "The amount of shares held in the strategy", + "example": "1277920000000000000000000" + } + }, + "required": [ + "strategyAddress", + "shares" + ] + }, + "description": "The list of strategy shares", + "example": [ + { + "strategyAddress": "0x93c4b944d05dfe6df7645a86cd2206016c51564d", + "shares": "1000288824523326631" + } + ] + }, + "startBlock": { + "type": "number", + "description": "The block number when the withdrawal was queued", + "example": 19912470 + }, + "createdAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was recorded by EigenExplorer", + "example": 19912470 + }, + "updatedAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was last updated", + "example": 19912470 + } + }, + "required": [ + "withdrawalRoot", + "nonce", + "isCompleted", + "stakerAddress", + "delegatedTo", + "withdrawerAddress", + "shares", + "startBlock", + "createdAtBlock", + "updatedAtBlock" + ] + } + }, + "meta": { + "type": "object", + "properties": { + "total": { + "type": "number", + "description": "Total number of records in the database", + "example": 30 + }, + "skip": { + "type": "number", + "description": "The number of skiped records for this query", + "example": 0 + }, + "take": { + "type": "number", + "description": "The number of records returned for this query", + "example": 12 + } + }, + "required": [ + "total", + "skip", + "take" + ] + } + }, + "required": [ + "data", + "meta" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/400" + }, + "401": { + "$ref": "#/components/responses/401" + }, + "403": { + "$ref": "#/components/responses/403" + }, + "404": { + "$ref": "#/components/responses/404" + }, + "422": { + "$ref": "#/components/responses/422" + }, + "429": { + "$ref": "#/components/responses/429" + }, + "500": { + "$ref": "#/components/responses/500" + } + } + } + }, + "/stakers/{address}/withdrawals/queued": { + "get": { + "operationId": "getQueuedStakerWithdrawals", + "summary": "Retrieve queued withdrawals by staker address", + "description": "Returns all queued withdrawal data of the requested staker.", + "tags": [ + "Stakers" + ], + "parameters": [ + { + "in": "path", + "name": "address", + "description": "The address of the staker", + "schema": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "required": true + }, + { + "in": "query", + "name": "total", + "description": "Total number of records in the database", + "schema": { + "type": "number", + "description": "Total number of records in the database", + "example": 30 + }, + "required": true + }, + { + "in": "query", + "name": "skip", + "description": "The number of skiped records for this query", + "schema": { + "type": "number", + "description": "The number of skiped records for this query", + "example": 0 + }, + "required": true + }, + { + "in": "query", + "name": "take", + "description": "The number of records returned for this query", + "schema": { + "type": "number", + "description": "The number of records returned for this query", + "example": 12 + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The list of queued withdrawals.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "withdrawalRoot": { + "type": "string", + "description": "The root hash of the withdrawal", + "example": "0x9e6728ef0a8ad6009107a886047aae35bc5ed7deaa68580b0d1f8f67e3e5ed31" + }, + "nonce": { + "type": "number", + "description": "The nonce of the withdrawal", + "example": 0 + }, + "isCompleted": { + "type": "boolean", + "description": "Indicates if the withdrawal is completed", + "example": false + }, + "stakerAddress": { + "type": "string", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "delegatedTo": { + "type": "string", + "description": "The operator address to which staking is delegated", + "example": "0x0000000000000000000000000000000000000000" + }, + "withdrawerAddress": { + "type": "string", + "description": "The address of the withdrawer", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "shares": { + "type": "array", + "items": { + "type": "object", + "properties": { + "strategyAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the restaking strategy", + "example": "0xbeac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0" + }, + "shares": { + "type": "string", + "description": "The amount of shares held in the strategy", + "example": "1277920000000000000000000" + } + }, + "required": [ + "strategyAddress", + "shares" + ] + }, + "description": "The list of strategy shares", + "example": [ + { + "strategyAddress": "0x93c4b944d05dfe6df7645a86cd2206016c51564d", + "shares": "1000288824523326631" + } + ] + }, + "startBlock": { + "type": "number", + "description": "The block number when the withdrawal was queued", + "example": 19912470 + }, + "createdAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was recorded by EigenExplorer", + "example": 19912470 + }, + "updatedAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was last updated", + "example": 19912470 + } + }, + "required": [ + "withdrawalRoot", + "nonce", + "isCompleted", + "stakerAddress", + "delegatedTo", + "withdrawerAddress", + "shares", + "startBlock", + "createdAtBlock", + "updatedAtBlock" + ] + } + }, + "meta": { + "type": "object", + "properties": { + "total": { + "type": "number", + "description": "Total number of records in the database", + "example": 30 + }, + "skip": { + "type": "number", + "description": "The number of skiped records for this query", + "example": 0 + }, + "take": { + "type": "number", + "description": "The number of records returned for this query", + "example": 12 + } + }, + "required": [ + "total", + "skip", + "take" + ] + } + }, + "required": [ + "data", + "meta" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/400" + }, + "401": { + "$ref": "#/components/responses/401" + }, + "403": { + "$ref": "#/components/responses/403" + }, + "404": { + "$ref": "#/components/responses/404" + }, + "422": { + "$ref": "#/components/responses/422" + }, + "429": { + "$ref": "#/components/responses/429" + }, + "500": { + "$ref": "#/components/responses/500" + } + } + } + }, + "/stakers/{address}/withdrawals/queued_withdrawable": { + "get": { + "operationId": "getQueuedWithdrawableStakerWithdrawals", + "summary": "Retrieve queued and withdrawable withdrawals by staker address", + "description": "Returns all queued and withdrawable withdrawal data of the requested staker.", + "tags": [ + "Stakers" + ], + "parameters": [ + { + "in": "path", + "name": "address", + "description": "The address of the staker", + "schema": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "required": true + }, + { + "in": "query", + "name": "total", + "description": "Total number of records in the database", + "schema": { + "type": "number", + "description": "Total number of records in the database", + "example": 30 + }, + "required": true + }, + { + "in": "query", + "name": "skip", + "description": "The number of skiped records for this query", + "schema": { + "type": "number", + "description": "The number of skiped records for this query", + "example": 0 + }, + "required": true + }, + { + "in": "query", + "name": "take", + "description": "The number of records returned for this query", + "schema": { + "type": "number", + "description": "The number of records returned for this query", + "example": 12 + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The list of queued and withdrawable withdrawals.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "withdrawalRoot": { + "type": "string", + "description": "The root hash of the withdrawal", + "example": "0x9e6728ef0a8ad6009107a886047aae35bc5ed7deaa68580b0d1f8f67e3e5ed31" + }, + "nonce": { + "type": "number", + "description": "The nonce of the withdrawal", + "example": 0 + }, + "isCompleted": { + "type": "boolean", + "description": "Indicates if the withdrawal is completed", + "example": false + }, + "stakerAddress": { + "type": "string", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "delegatedTo": { + "type": "string", + "description": "The operator address to which staking is delegated", + "example": "0x0000000000000000000000000000000000000000" + }, + "withdrawerAddress": { + "type": "string", + "description": "The address of the withdrawer", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "shares": { + "type": "array", + "items": { + "type": "object", + "properties": { + "strategyAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the restaking strategy", + "example": "0xbeac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0" + }, + "shares": { + "type": "string", + "description": "The amount of shares held in the strategy", + "example": "1277920000000000000000000" + } + }, + "required": [ + "strategyAddress", + "shares" + ] + }, + "description": "The list of strategy shares", + "example": [ + { + "strategyAddress": "0x93c4b944d05dfe6df7645a86cd2206016c51564d", + "shares": "1000288824523326631" + } + ] + }, + "startBlock": { + "type": "number", + "description": "The block number when the withdrawal was queued", + "example": 19912470 + }, + "createdAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was recorded by EigenExplorer", + "example": 19912470 + }, + "updatedAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was last updated", + "example": 19912470 + } + }, + "required": [ + "withdrawalRoot", + "nonce", + "isCompleted", + "stakerAddress", + "delegatedTo", + "withdrawerAddress", + "shares", + "startBlock", + "createdAtBlock", + "updatedAtBlock" + ] + } + }, + "meta": { + "type": "object", + "properties": { + "total": { + "type": "number", + "description": "Total number of records in the database", + "example": 30 + }, + "skip": { + "type": "number", + "description": "The number of skiped records for this query", + "example": 0 + }, + "take": { + "type": "number", + "description": "The number of records returned for this query", + "example": 12 + } + }, + "required": [ + "total", + "skip", + "take" + ] + } + }, + "required": [ + "data", + "meta" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/400" + }, + "401": { + "$ref": "#/components/responses/401" + }, + "403": { + "$ref": "#/components/responses/403" + }, + "404": { + "$ref": "#/components/responses/404" + }, + "422": { + "$ref": "#/components/responses/422" + }, + "429": { + "$ref": "#/components/responses/429" + }, + "500": { + "$ref": "#/components/responses/500" + } + } + } + }, + "/stakers/{address}/withdrawals/completed": { + "get": { + "operationId": "getCompletedStakerWithdrawals", + "summary": "Retrieve completed withdrawals by staker address", + "description": "Returns all completed withdrawal data of the requested staker.", + "tags": [ + "Stakers" + ], + "parameters": [ + { + "in": "path", + "name": "address", + "description": "The address of the staker", + "schema": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "required": true + }, + { + "in": "query", + "name": "total", + "description": "Total number of records in the database", + "schema": { + "type": "number", + "description": "Total number of records in the database", + "example": 30 + }, + "required": true + }, + { + "in": "query", + "name": "skip", + "description": "The number of skiped records for this query", + "schema": { + "type": "number", + "description": "The number of skiped records for this query", + "example": 0 + }, + "required": true + }, + { + "in": "query", + "name": "take", + "description": "The number of records returned for this query", + "schema": { + "type": "number", + "description": "The number of records returned for this query", + "example": 12 + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The list of completed withdrawals.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "withdrawalRoot": { + "type": "string", + "description": "The root hash of the withdrawal", + "example": "0x9e6728ef0a8ad6009107a886047aae35bc5ed7deaa68580b0d1f8f67e3e5ed31" + }, + "nonce": { + "type": "number", + "description": "The nonce of the withdrawal", + "example": 0 + }, + "isCompleted": { + "type": "boolean", + "description": "Indicates if the withdrawal is completed", + "example": false + }, + "stakerAddress": { + "type": "string", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "delegatedTo": { + "type": "string", + "description": "The operator address to which staking is delegated", + "example": "0x0000000000000000000000000000000000000000" + }, + "withdrawerAddress": { + "type": "string", + "description": "The address of the withdrawer", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "shares": { + "type": "array", + "items": { + "type": "object", + "properties": { + "strategyAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the restaking strategy", + "example": "0xbeac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0" + }, + "shares": { + "type": "string", + "description": "The amount of shares held in the strategy", + "example": "1277920000000000000000000" + } + }, + "required": [ + "strategyAddress", + "shares" + ] + }, + "description": "The list of strategy shares", + "example": [ + { + "strategyAddress": "0x93c4b944d05dfe6df7645a86cd2206016c51564d", + "shares": "1000288824523326631" + } + ] + }, + "startBlock": { + "type": "number", + "description": "The block number when the withdrawal was queued", + "example": 19912470 + }, + "createdAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was recorded by EigenExplorer", + "example": 19912470 + }, + "updatedAtBlock": { + "type": "number", + "description": "The block number when the withdrawal was last updated", + "example": 19912470 + } + }, + "required": [ + "withdrawalRoot", + "nonce", + "isCompleted", + "stakerAddress", + "delegatedTo", + "withdrawerAddress", + "shares", + "startBlock", + "createdAtBlock", + "updatedAtBlock" + ] + } + }, + "meta": { + "type": "object", + "properties": { + "total": { + "type": "number", + "description": "Total number of records in the database", + "example": 30 + }, + "skip": { + "type": "number", + "description": "The number of skiped records for this query", + "example": 0 + }, + "take": { + "type": "number", + "description": "The number of records returned for this query", + "example": 12 + } + }, + "required": [ + "total", + "skip", + "take" + ] + } + }, + "required": [ + "data", + "meta" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/400" + }, + "401": { + "$ref": "#/components/responses/401" + }, + "403": { + "$ref": "#/components/responses/403" + }, + "404": { + "$ref": "#/components/responses/404" + }, + "422": { + "$ref": "#/components/responses/422" + }, + "429": { + "$ref": "#/components/responses/429" + }, + "500": { + "$ref": "#/components/responses/500" + } + } + } } }, "components": { diff --git a/packages/openapi/src/apiResponseSchema/operatorResponse.ts b/packages/openapi/src/apiResponseSchema/operatorResponse.ts index 26335906..c55a6b64 100644 --- a/packages/openapi/src/apiResponseSchema/operatorResponse.ts +++ b/packages/openapi/src/apiResponseSchema/operatorResponse.ts @@ -51,35 +51,3 @@ export const OperatorResponseSchema = z.object({ }, }), }); - -// const OperatorSharesSchema = z.object({ -// strategyAddress: EthereumAddressSchema.describe( -// 'The contract address of the restaking strategy' -// ).openapi({ example: '0x298afb19a105d59e74658c4c334ff360bade6dd2' }), -// shares: z -// .string() -// .describe('The amount of shares held in the strategy for this operator') -// .openapi({ example: '40888428658906049' }), -// }); - -// export const IndividualOperatorResponseSchema = z.object({ -// address: EthereumAddressSchema.describe( -// 'The contract address of the AVS operator' -// ).openapi({ example: '0x09e6eb09213bdd3698bd8afb43ec3cb0ecff683a' }), -// metadataName: OperatorMetaDataSchema.shape.metadataName, -// metadataDescription: OperatorMetaDataSchema.shape.metadataDescription, -// metadataDiscord: OperatorMetaDataSchema.shape.metadataDiscord, -// metadataLogo: OperatorMetaDataSchema.shape.metadataLogo, -// metadataTelegram: OperatorMetaDataSchema.shape.metadataTelegram, -// metadataWebsite: OperatorMetaDataSchema.shape.metadataWebsite, -// metadataX: OperatorMetaDataSchema.shape.metadataX, -// shares: z.array(OperatorSharesSchema), -// tvl: z -// .number() -// .describe('The total value locked in the AVS operator') -// .openapi({ example: 1000000 }), -// totalStakers: z -// .number() -// .describe('The total number of stakers opted into the AVS operator') -// .openapi({ example: 10 }), -// }); diff --git a/packages/openapi/src/apiResponseSchema/withdrawals/withdrawalsResponseSchema.ts b/packages/openapi/src/apiResponseSchema/withdrawals/withdrawalsResponseSchema.ts new file mode 100644 index 00000000..072db0a6 --- /dev/null +++ b/packages/openapi/src/apiResponseSchema/withdrawals/withdrawalsResponseSchema.ts @@ -0,0 +1,58 @@ +import z from '../../../../api/src/schema/zod'; +import { StrategySharesSchema } from '../../../../api/src/schema/zod/schemas/base/strategyShares'; + +export const WithdrawalsResponseSchema = z.object({ + withdrawalRoot: z + .string() + .describe('The root hash of the withdrawal') + .openapi({ + example: + '0x9e6728ef0a8ad6009107a886047aae35bc5ed7deaa68580b0d1f8f67e3e5ed31', + }), + nonce: z + .number() + .describe('The nonce of the withdrawal') + .openapi({ example: 0 }), + isCompleted: z + .boolean() + .describe('Indicates if the withdrawal is completed') + .openapi({ example: false }), + stakerAddress: z + .string() + .describe('The address of the staker') + .openapi({ example: '0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd' }), + delegatedTo: z + .string() + .describe('The operator address to which staking is delegated') + .openapi({ example: '0x0000000000000000000000000000000000000000' }), + withdrawerAddress: z + .string() + .describe('The address of the withdrawer') + .openapi({ example: '0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd' }), + shares: z + .array(StrategySharesSchema) + .describe('The list of strategy shares') + .openapi({ + example: [ + { + strategyAddress: + '0x93c4b944d05dfe6df7645a86cd2206016c51564d', + shares: '1000288824523326631', + }, + ], + }), + startBlock: z + .number() + .describe('The block number when the withdrawal was queued') + .openapi({ example: 19912470 }), + createdAtBlock: z + .number() + .describe( + 'The block number when the withdrawal was recorded by EigenExplorer' + ) + .openapi({ example: 19912470 }), + updatedAtBlock: z + .number() + .describe('The block number when the withdrawal was last updated') + .openapi({ example: 19912470 }), +}); diff --git a/packages/openapi/src/documentBase.ts b/packages/openapi/src/documentBase.ts index e37aeac2..35b92579 100644 --- a/packages/openapi/src/documentBase.ts +++ b/packages/openapi/src/documentBase.ts @@ -3,6 +3,8 @@ import { createDocument } from 'zod-openapi'; import { avsRoutes } from './routes/avs'; import { metricsRoutes } from './routes/metrics'; import { operatorsRoutes } from './routes/operators'; +import { withdrawalsRoutes } from './routes/withdrawals'; +import { stakersRoutes } from './routes/stakers'; export const document = createDocument({ openapi: '3.0.3', @@ -26,6 +28,8 @@ export const document = createDocument({ ...metricsRoutes, ...avsRoutes, ...operatorsRoutes, + ...withdrawalsRoutes, + ...stakersRoutes, }, components: { schemas: {}, diff --git a/packages/openapi/src/routes/avs/getAllAvs.ts b/packages/openapi/src/routes/avs/getAllAvs.ts index 0055211e..ce9590ad 100644 --- a/packages/openapi/src/routes/avs/getAllAvs.ts +++ b/packages/openapi/src/routes/avs/getAllAvs.ts @@ -13,8 +13,8 @@ const AvsResponseSchema = z.object({ const CombinedQuerySchema = z .object({}) - .merge(PaginationQuerySchema) - .merge(WithTvlQuerySchema); + .merge(WithTvlQuerySchema) + .merge(PaginationQuerySchema); export const getAllAvs: ZodOpenApiOperationObject = { operationId: 'getAllAvs', diff --git a/packages/openapi/src/routes/avs/getAvsOperatorsByAddress.ts b/packages/openapi/src/routes/avs/getAvsOperatorsByAddress.ts index 2a4f98cf..813443a2 100644 --- a/packages/openapi/src/routes/avs/getAvsOperatorsByAddress.ts +++ b/packages/openapi/src/routes/avs/getAvsOperatorsByAddress.ts @@ -18,8 +18,8 @@ const AvsOperatorResponseSchema = z.object({ const CombinedQuerySchema = z .object({}) - .merge(PaginationQuerySchema) - .merge(WithTvlQuerySchema); + .merge(WithTvlQuerySchema) + .merge(PaginationQuerySchema); export const getAvsOperatorsByAddress: ZodOpenApiOperationObject = { operationId: 'getAvsOperatorsByAddress', diff --git a/packages/openapi/src/routes/operators/getAllOperators.ts b/packages/openapi/src/routes/operators/getAllOperators.ts index 2a37779f..d831ec70 100644 --- a/packages/openapi/src/routes/operators/getAllOperators.ts +++ b/packages/openapi/src/routes/operators/getAllOperators.ts @@ -13,8 +13,8 @@ const AllOperatorsResponseSchema = z.object({ const CombinedQuerySchema = z .object({}) - .merge(PaginationQuerySchema) - .merge(WithTvlQuerySchema); + .merge(WithTvlQuerySchema) + .merge(PaginationQuerySchema); export const getAllOperators: ZodOpenApiOperationObject = { operationId: 'getAllOperators', diff --git a/packages/openapi/src/routes/operators/getOperatorByAddress.ts b/packages/openapi/src/routes/operators/getOperatorByAddress.ts index 19cbf396..ebd3c131 100644 --- a/packages/openapi/src/routes/operators/getOperatorByAddress.ts +++ b/packages/openapi/src/routes/operators/getOperatorByAddress.ts @@ -7,7 +7,7 @@ import { WithTvlQuerySchema } from '../../../../api/src/schema/zod/schemas/withT const OperatorAddressParam = z.object({ address: EthereumAddressSchema.describe( - 'The address of the operator.' + 'The address of the operator' ).openapi({ example: '0x00107cfdeaddc0a3160ed2f6fedd627f313e7b1b' }), }); diff --git a/packages/openapi/src/routes/stakers/getCompletedStakerWithdrawals.ts b/packages/openapi/src/routes/stakers/getCompletedStakerWithdrawals.ts new file mode 100644 index 00000000..670ce65d --- /dev/null +++ b/packages/openapi/src/routes/stakers/getCompletedStakerWithdrawals.ts @@ -0,0 +1,40 @@ +import z from '../../../../api/src/schema/zod'; +import { ZodOpenApiOperationObject } from 'zod-openapi'; +import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; +import { PaginationMetaResponsesSchema } from '../../apiResponseSchema/base/paginationMetaResponses'; +import { WithdrawalsResponseSchema } from '../../apiResponseSchema/withdrawals/withdrawalsResponseSchema'; +import { EthereumAddressSchema } from '../../../../api/src/schema/zod/schemas/base/ethereumAddress'; + +const WithdrawalsResponseSchemaWithMeta = z.object({ + data: z.array(WithdrawalsResponseSchema), + meta: PaginationMetaResponsesSchema, +}); + +const StakerAddressParam = z.object({ + address: EthereumAddressSchema.describe( + 'The address of the staker' + ).openapi({ example: '0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd' }), +}); + +export const getCompletedStakerWithdrawals: ZodOpenApiOperationObject = { + operationId: 'getCompletedStakerWithdrawals', + summary: 'Retrieve completed withdrawals by staker address', + description: + 'Returns all completed withdrawal data of the requested staker.', + tags: ['Stakers'], + requestParams: { + path: StakerAddressParam, + query: PaginationMetaResponsesSchema, + }, + responses: { + '200': { + description: 'The list of completed withdrawals.', + content: { + 'application/json': { + schema: WithdrawalsResponseSchemaWithMeta, + }, + }, + }, + ...openApiErrorResponses, + }, +}; diff --git a/packages/openapi/src/routes/stakers/getQueuedStakerWithdrawals.ts b/packages/openapi/src/routes/stakers/getQueuedStakerWithdrawals.ts new file mode 100644 index 00000000..fd3c4684 --- /dev/null +++ b/packages/openapi/src/routes/stakers/getQueuedStakerWithdrawals.ts @@ -0,0 +1,39 @@ +import z from '../../../../api/src/schema/zod'; +import { ZodOpenApiOperationObject } from 'zod-openapi'; +import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; +import { PaginationMetaResponsesSchema } from '../../apiResponseSchema/base/paginationMetaResponses'; +import { WithdrawalsResponseSchema } from '../../apiResponseSchema/withdrawals/withdrawalsResponseSchema'; +import { EthereumAddressSchema } from '../../../../api/src/schema/zod/schemas/base/ethereumAddress'; + +const WithdrawalsResponseSchemaWithMeta = z.object({ + data: z.array(WithdrawalsResponseSchema), + meta: PaginationMetaResponsesSchema, +}); + +const StakerAddressParam = z.object({ + address: EthereumAddressSchema.describe( + 'The address of the staker' + ).openapi({ example: '0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd' }), +}); + +export const getQueuedStakerWithdrawals: ZodOpenApiOperationObject = { + operationId: 'getQueuedStakerWithdrawals', + summary: 'Retrieve queued withdrawals by staker address', + description: 'Returns all queued withdrawal data of the requested staker.', + tags: ['Stakers'], + requestParams: { + path: StakerAddressParam, + query: PaginationMetaResponsesSchema, + }, + responses: { + '200': { + description: 'The list of queued withdrawals.', + content: { + 'application/json': { + schema: WithdrawalsResponseSchemaWithMeta, + }, + }, + }, + ...openApiErrorResponses, + }, +}; diff --git a/packages/openapi/src/routes/stakers/getQueuedWithdrawableStakerWithdrawals.ts b/packages/openapi/src/routes/stakers/getQueuedWithdrawableStakerWithdrawals.ts new file mode 100644 index 00000000..a4744390 --- /dev/null +++ b/packages/openapi/src/routes/stakers/getQueuedWithdrawableStakerWithdrawals.ts @@ -0,0 +1,42 @@ +import z from '../../../../api/src/schema/zod'; +import { ZodOpenApiOperationObject } from 'zod-openapi'; +import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; +import { PaginationMetaResponsesSchema } from '../../apiResponseSchema/base/paginationMetaResponses'; +import { WithdrawalsResponseSchema } from '../../apiResponseSchema/withdrawals/withdrawalsResponseSchema'; +import { EthereumAddressSchema } from '../../../../api/src/schema/zod/schemas/base/ethereumAddress'; + +const WithdrawalsResponseSchemaWithMeta = z.object({ + data: z.array(WithdrawalsResponseSchema), + meta: PaginationMetaResponsesSchema, +}); + +const StakerAddressParam = z.object({ + address: EthereumAddressSchema.describe( + 'The address of the staker' + ).openapi({ example: '0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd' }), +}); + +export const getQueuedWithdrawableStakerWithdrawals: ZodOpenApiOperationObject = + { + operationId: 'getQueuedWithdrawableStakerWithdrawals', + summary: + 'Retrieve queued and withdrawable withdrawals by staker address', + description: + 'Returns all queued and withdrawable withdrawal data of the requested staker.', + tags: ['Stakers'], + requestParams: { + path: StakerAddressParam, + query: PaginationMetaResponsesSchema, + }, + responses: { + '200': { + description: 'The list of queued and withdrawable withdrawals.', + content: { + 'application/json': { + schema: WithdrawalsResponseSchemaWithMeta, + }, + }, + }, + ...openApiErrorResponses, + }, + }; diff --git a/packages/openapi/src/routes/stakers/getStakerWithdrawals.ts b/packages/openapi/src/routes/stakers/getStakerWithdrawals.ts new file mode 100644 index 00000000..2ac427cc --- /dev/null +++ b/packages/openapi/src/routes/stakers/getStakerWithdrawals.ts @@ -0,0 +1,40 @@ +import z from '../../../../api/src/schema/zod'; +import { ZodOpenApiOperationObject } from 'zod-openapi'; +import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; +import { PaginationMetaResponsesSchema } from '../../apiResponseSchema/base/paginationMetaResponses'; +import { WithdrawalsResponseSchema } from '../../apiResponseSchema/withdrawals/withdrawalsResponseSchema'; +import { EthereumAddressSchema } from '../../../../api/src/schema/zod/schemas/base/ethereumAddress'; + +const WithdrawalsResponseSchemaWithMeta = z.object({ + data: z.array(WithdrawalsResponseSchema), + meta: PaginationMetaResponsesSchema, +}); + +const StakerAddressParam = z.object({ + address: EthereumAddressSchema.describe( + 'The address of the staker' + ).openapi({ example: '0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd' }), +}); + +export const getStakerWithdrawals: ZodOpenApiOperationObject = { + operationId: 'getStakerWithdrawals', + summary: 'Retrieve all withdrawals by staker address', + description: + 'Returns all withdrawal data of the requested staker, including the withdrawal root, nonce, withdrawal status, and other relevant information.', + tags: ['Stakers'], + requestParams: { + path: StakerAddressParam, + query: PaginationMetaResponsesSchema, + }, + responses: { + '200': { + description: 'The list of withdrawals.', + content: { + 'application/json': { + schema: WithdrawalsResponseSchemaWithMeta, + }, + }, + }, + ...openApiErrorResponses, + }, +}; diff --git a/packages/openapi/src/routes/stakers/index.ts b/packages/openapi/src/routes/stakers/index.ts new file mode 100644 index 00000000..e365878a --- /dev/null +++ b/packages/openapi/src/routes/stakers/index.ts @@ -0,0 +1,20 @@ +import { ZodOpenApiPathsObject } from 'zod-openapi'; +import { getStakerWithdrawals } from './getStakerWithdrawals'; +import { getQueuedStakerWithdrawals } from './getQueuedStakerWithdrawals'; +import { getQueuedWithdrawableStakerWithdrawals } from './getQueuedWithdrawableStakerWithdrawals'; +import { getCompletedStakerWithdrawals } from './getCompletedStakerWithdrawals'; + +export const stakersRoutes: ZodOpenApiPathsObject = { + '/stakers/{address}/withdrawals': { + get: getStakerWithdrawals, + }, + '/stakers/{address}/withdrawals/queued': { + get: getQueuedStakerWithdrawals, + }, + '/stakers/{address}/withdrawals/queued_withdrawable': { + get: getQueuedWithdrawableStakerWithdrawals, + }, + '/stakers/{address}/withdrawals/completed': { + get: getCompletedStakerWithdrawals, + }, +}; diff --git a/packages/openapi/src/routes/withdrawals/getAllWithdrawals.ts b/packages/openapi/src/routes/withdrawals/getAllWithdrawals.ts new file mode 100644 index 00000000..085f2972 --- /dev/null +++ b/packages/openapi/src/routes/withdrawals/getAllWithdrawals.ts @@ -0,0 +1,39 @@ +import z from '../../../../api/src/schema/zod'; +import { ZodOpenApiOperationObject } from 'zod-openapi'; +import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; +import { PaginationQuerySchema } from '../../../../api/src/schema/zod/schemas/paginationQuery'; +import { WithdrawalListQuerySchema } from '../../../../api/src/schema/zod/schemas/withdrawal'; +import { PaginationMetaResponsesSchema } from '../../apiResponseSchema/base/paginationMetaResponses'; +import { WithdrawalsResponseSchema } from '../../apiResponseSchema/withdrawals/withdrawalsResponseSchema'; + +const WithdrawalsResponseSchemaWithMeta = z.object({ + data: z.array(WithdrawalsResponseSchema), + meta: PaginationMetaResponsesSchema, +}); + +const CombinedQuerySchema = z + .object({}) + .merge(WithdrawalListQuerySchema) + .merge(PaginationQuerySchema); + +export const getAllWithdrawals: ZodOpenApiOperationObject = { + operationId: 'getAllWithdrawals', + summary: 'Retrieve all withdrawals', + description: + 'Returns all withdrawal data, including the withdrawal root, nonce, withdrawal status, and other relevant information.', + tags: ['Withdrawals'], + requestParams: { + query: CombinedQuerySchema, + }, + responses: { + '200': { + description: 'The list of withdrawals.', + content: { + 'application/json': { + schema: WithdrawalsResponseSchemaWithMeta, + }, + }, + }, + ...openApiErrorResponses, + }, +}; diff --git a/packages/openapi/src/routes/withdrawals/getWithdralByWithdrawalRoot.ts b/packages/openapi/src/routes/withdrawals/getWithdralByWithdrawalRoot.ts new file mode 100644 index 00000000..9177ac62 --- /dev/null +++ b/packages/openapi/src/routes/withdrawals/getWithdralByWithdrawalRoot.ts @@ -0,0 +1,35 @@ +import z from '../../../../api/src/schema/zod'; +import { ZodOpenApiOperationObject } from 'zod-openapi'; +import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; +import { WithdrawalsResponseSchema } from '../../apiResponseSchema/withdrawals/withdrawalsResponseSchema'; + +const WithdrawalRootParam = z.object({ + withdrawalRoot: z + .string() + .describe('The root hash of the withdrawal') + .openapi({ + example: + '0x9e6728ef0a8ad6009107a886047aae35bc5ed7deaa68580b0d1f8f67e3e5ed31', + }), +}); + +export const getWithdrawalByWithdrawalRoot: ZodOpenApiOperationObject = { + operationId: 'getWithdrawalByWithdrawalRoot', + summary: 'Retrieve withdrawal by withdrawal root', + description: 'Returns the withdrawal data by withdrawal root.', + tags: ['Withdrawals'], + requestParams: { + path: WithdrawalRootParam, + }, + responses: { + '200': { + description: 'The requested withdrawal record.', + content: { + 'application/json': { + schema: WithdrawalsResponseSchema, + }, + }, + }, + ...openApiErrorResponses, + }, +}; diff --git a/packages/openapi/src/routes/withdrawals/index.ts b/packages/openapi/src/routes/withdrawals/index.ts new file mode 100644 index 00000000..ba1bd525 --- /dev/null +++ b/packages/openapi/src/routes/withdrawals/index.ts @@ -0,0 +1,12 @@ +import { ZodOpenApiPathsObject } from 'zod-openapi'; +import { getAllWithdrawals } from './getAllWithdrawals'; +import { getWithdrawalByWithdrawalRoot } from './getWithdralByWithdrawalRoot'; + +export const withdrawalsRoutes: ZodOpenApiPathsObject = { + '/withdrawals': { + get: getAllWithdrawals, + }, + '/withdrawals/{withdrawalRoot}': { + get: getWithdrawalByWithdrawalRoot, + }, +}; From 0f60a53169a3950662e4bee0220639a68e9111ac Mon Sep 17 00:00:00 2001 From: Liam Zhang Date: Thu, 23 May 2024 21:04:16 -0700 Subject: [PATCH 10/62] withdrawal api --- .env.example | 3 ++ .../api/src/schema/zod/schemas/withdrawal.ts | 43 +++++++++++-------- 2 files changed, 28 insertions(+), 18 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..f8538912 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +PORT = 3002 +RPC_WSS_URL = "" +DATABASE_URL = "" \ No newline at end of file diff --git a/packages/api/src/schema/zod/schemas/withdrawal.ts b/packages/api/src/schema/zod/schemas/withdrawal.ts index 1d91c029..54b47ff5 100644 --- a/packages/api/src/schema/zod/schemas/withdrawal.ts +++ b/packages/api/src/schema/zod/schemas/withdrawal.ts @@ -1,20 +1,27 @@ -import z from '../' +import z from '../'; export const WithdrawalListQuerySchema = z.object({ - stakerAddress: z - .string() - .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') - .optional(), - - delegatedTo: z - .string() - .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') - .optional(), - - strategyAddress: z - .string() - .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') - .optional(), - - status: z.enum(['queued', 'queued_withdrawable', 'completed']).optional() -}) + stakerAddress: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') + .optional() + .describe('The address of the staker') + .openapi({ example: '0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd' }), + delegatedTo: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') + .optional() + .describe('The address of the operator to which the stake is delegated') + .openapi({ example: '0x5accc90436492f24e6af278569691e2c942a676d' }), + strategyAddress: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') + .optional() + .describe('The contract address of the restaking strategy') + .openapi({ example: '0x0fe4f44bee93503346a3ac9ee5a26b130a5796d6' }), + status: z + .enum(['queued', 'queued_withdrawable', 'completed']) + .optional() + .describe('The status of the withdrawal') + .openapi({ example: 'queued' }), +}); From 2ddd55019cff94d312db58776ffdd2d2e5a52201 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Thu, 23 May 2024 00:42:15 +0530 Subject: [PATCH 11/62] added historical count route for avs --- .../src/routes/metrics/metricController.ts | 94 ++++++++++++++++++- .../api/src/routes/metrics/metricRoutes.ts | 49 +++++----- .../zod/schemas/historicalCountQuery.ts | 32 +++++++ packages/api/src/utils/blockNumber.ts | 25 +++++ 4 files changed, 178 insertions(+), 22 deletions(-) create mode 100644 packages/api/src/schema/zod/schemas/historicalCountQuery.ts create mode 100644 packages/api/src/utils/blockNumber.ts diff --git a/packages/api/src/routes/metrics/metricController.ts b/packages/api/src/routes/metrics/metricController.ts index 4188c1ba..26be2a65 100644 --- a/packages/api/src/routes/metrics/metricController.ts +++ b/packages/api/src/routes/metrics/metricController.ts @@ -6,8 +6,10 @@ import { strategyAbi } from '../../data/abi/strategy' import { getEigenContracts } from '../../data/address' import { handleAndReturnErrorResponse } from '../../schema/errors' import { getAvsFilterQuery } from '../avs/avsController' +import { getBlockNumberFromDate } from '../../utils/blockNumber' import { fetchStrategyTokenPrices } from '../../utils/tokenPrices' import { getStrategiesWithShareUnderlying } from '../strategies/strategiesController' +import { HistoricalCountSchema } from '../../schema/zod/schemas/historicalCountQuery' /** * Route to get explorer metrics @@ -80,7 +82,9 @@ export async function getTvlRestakingByStrategy(req: Request, res: Response) { } const strategies = Object.keys(getEigenContracts().Strategies) - const foundStrategy = strategies.find(s => s.toLowerCase() === strategy.toLowerCase()) + const foundStrategy = strategies.find( + (s) => s.toLowerCase() === strategy.toLowerCase() + ) if (!foundStrategy) { throw new Error('Invalid strategy.') @@ -134,6 +138,26 @@ export async function getTotalStakers(req: Request, res: Response) { } } +export async function getHistoricalAvsCount(req: Request, res: Response) { + const paramCheck = HistoricalCountSchema.safeParse(req.query) + if (!paramCheck.success) { + return handleAndReturnErrorResponse(req, res, paramCheck.error) + } + + try { + const { frequency, variant, startAt, endAt } = paramCheck.data + const data = await doGetHistoricalAvsCount( + startAt, + endAt, + frequency, + variant + ) + res.status(200).send({ data }) + } catch (error) { + handleAndReturnErrorResponse(req, res, error) + } +} + // ================================================ async function doGetTvl() { @@ -237,3 +261,71 @@ async function doGetTotalStakerCount() { return stakers } + +async function doGetHistoricalAvsCount( + startAt: string, + endAt: string, + frequency: string, + variant: string +) { + const viemClient = getViemClient() + const chainId = await viemClient.getChainId() + + const startDate = new Date(startAt) + const endDate = new Date(endAt) + + const startBlockNumber = await getBlockNumberFromDate(startDate, chainId) + const endBlockNumber = await getBlockNumberFromDate(endDate, chainId) + + const avsData = await prisma.avs.findMany({ + where: { + createdAtBlock: { + gte: startBlockNumber, + lte: endBlockNumber + } + }, + orderBy: { + createdAtBlock: 'asc' + } + }) + + let tally = 0 + const results: { ts: string; value: number }[] = [] + let currentDate = new Date(startDate) + + const timeInterval = + { + '1h': 3600000, + '1d': 86400000, + '7d': 604800000 + }[frequency] || 3600000 + + while (currentDate <= endDate) { + const nextDate = new Date(currentDate.getTime() + timeInterval) + const currentBlockNumber = await getBlockNumberFromDate( + currentDate, + chainId + ) + const nextBlockNumber = await getBlockNumberFromDate(nextDate, chainId) + + const intervalData = avsData.filter( + (avs) => + avs.createdAtBlock >= currentBlockNumber && + avs.createdAtBlock < nextBlockNumber + ) + + if (variant === 'count') { + results.push({ + ts: currentDate.toISOString(), + value: intervalData.length + }) + } else { + tally += intervalData.length + results.push({ ts: currentDate.toISOString(), value: tally }) + } + + currentDate = nextDate + } + + return results +} diff --git a/packages/api/src/routes/metrics/metricRoutes.ts b/packages/api/src/routes/metrics/metricRoutes.ts index 5ed819fa..26fb5aaa 100644 --- a/packages/api/src/routes/metrics/metricRoutes.ts +++ b/packages/api/src/routes/metrics/metricRoutes.ts @@ -1,35 +1,42 @@ -import express from 'express'; +import express from 'express' import { - getMetrics, - getTotalAvs, - getTotalOperators, - getTotalStakers, - getTvl, - getTvlBeaconChain, - getTvlRestaking, - getTvlRestakingByStrategy, -} from './metricController'; + getMetrics, + getTotalAvs, + getTotalOperators, + getTotalStakers, + getTvl, + getTvlBeaconChain, + getTvlRestaking, + getTvlRestakingByStrategy, + getHistoricalAvsCount +} from './metricController' -import routeCache from "route-cache"; +import routeCache from 'route-cache' -const router = express.Router(); +const router = express.Router() // API routes for /metrics -router.get('/', routeCache.cacheSeconds(120), getMetrics); +router.get('/', routeCache.cacheSeconds(120), getMetrics) -router.get('/tvl', routeCache.cacheSeconds(120), getTvl); +router.get('/tvl', routeCache.cacheSeconds(120), getTvl) -router.get('/tvl/beacon-chain', routeCache.cacheSeconds(120), getTvlBeaconChain); +router.get('/tvl/beacon-chain', routeCache.cacheSeconds(120), getTvlBeaconChain) -router.get('/tvl/restaking', routeCache.cacheSeconds(120), getTvlRestaking); +router.get('/tvl/restaking', routeCache.cacheSeconds(120), getTvlRestaking) -router.get('/tvl/restaking/:strategy', routeCache.cacheSeconds(120), getTvlRestakingByStrategy); +router.get( + '/tvl/restaking/:strategy', + routeCache.cacheSeconds(120), + getTvlRestakingByStrategy +) -router.get('/total-avs', routeCache.cacheSeconds(120), getTotalAvs); +router.get('/total-avs', routeCache.cacheSeconds(120), getTotalAvs) -router.get('/total-operators', routeCache.cacheSeconds(120), getTotalOperators); +router.get('/total-operators', routeCache.cacheSeconds(120), getTotalOperators) -router.get('/total-stakers', routeCache.cacheSeconds(120), getTotalStakers); +router.get('/total-stakers', routeCache.cacheSeconds(120), getTotalStakers) -export default router; +router.get('/historical/avs', routeCache.cacheSeconds(120), getHistoricalAvsCount) + +export default router diff --git a/packages/api/src/schema/zod/schemas/historicalCountQuery.ts b/packages/api/src/schema/zod/schemas/historicalCountQuery.ts new file mode 100644 index 00000000..6ab234e2 --- /dev/null +++ b/packages/api/src/schema/zod/schemas/historicalCountQuery.ts @@ -0,0 +1,32 @@ +import z from '..' + +export const HistoricalCountSchema = z.object({ + frequency: z + .enum(['1h', '1d', '7d']) + .default('1h') + .describe('Frequency of data points'), + variant: z + .enum(['count', 'cumulative']) + .default('cumulative') + .describe('Type of tally, count or cumulative'), + startAt: z + .string() + .optional() + .describe('Start date in ISO string format') + .refine((val) => !val || !Number.isNaN(Date.parse(val)), { + message: 'Invalid date format' + }) + .default(() => new Date(Date.now() - 86400000).toISOString()) // Default to 1 day ago + .describe('Start date in ISO string format'), + endAt: z + .string() + .optional() + .describe('End date in ISO string format') + .refine((val) => !val || !Number.isNaN(Date.parse(val)), { + message: 'Invalid date format' + }) + .default(() => new Date().toISOString()) // Default to now + .describe('End date in ISO string format') +}) + +export default HistoricalCountSchema diff --git a/packages/api/src/utils/blockNumber.ts b/packages/api/src/utils/blockNumber.ts new file mode 100644 index 00000000..711e60fb --- /dev/null +++ b/packages/api/src/utils/blockNumber.ts @@ -0,0 +1,25 @@ +import { cacheStore } from 'route-cache' + +export async function getBlockNumberFromDate(date: Date, chainId: number) { + const timestamp = Math.floor(date.getTime() / 1000) + const cacheKey = `block_${timestamp}` + const cachedValue = await cacheStore.get(cacheKey) + + if (cachedValue) { + return cachedValue.height + } + + const response = + chainId === 1 + ? await fetch(`https://coins.llama.fi/block/ethereum/${timestamp}`) + : await fetch(`https://coins.llama.fi/block/holesky/${timestamp}`) + + if (!response.ok) { + throw new Error('Failed to fetch block number from date') + } + + const data = await response.json() + await cacheStore.set(cacheKey, data, 120_000) // Cache for 2 minutes (120,000 milliseconds) + + return data.height +} From 5ffe0b8f248153f280ea0553c4d12584177529ba Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Thu, 23 May 2024 14:54:00 +0530 Subject: [PATCH 12/62] added count routes for operator & staker --- .../src/routes/metrics/metricController.ts | 164 +++++++++++++++--- .../api/src/routes/metrics/metricRoutes.ts | 22 ++- packages/api/src/utils/blockNumber.ts | 25 --- 3 files changed, 162 insertions(+), 49 deletions(-) delete mode 100644 packages/api/src/utils/blockNumber.ts diff --git a/packages/api/src/routes/metrics/metricController.ts b/packages/api/src/routes/metrics/metricController.ts index 26be2a65..23a4d353 100644 --- a/packages/api/src/routes/metrics/metricController.ts +++ b/packages/api/src/routes/metrics/metricController.ts @@ -146,7 +146,50 @@ export async function getHistoricalAvsCount(req: Request, res: Response) { try { const { frequency, variant, startAt, endAt } = paramCheck.data - const data = await doGetHistoricalAvsCount( + const data = await doGetHistoricalCount( + 'avs', + startAt, + endAt, + frequency, + variant + ) + res.status(200).send({ data }) + } catch (error) { + handleAndReturnErrorResponse(req, res, error) + } +} + +export async function getHistoricalOperatorCount(req: Request, res: Response) { + const paramCheck = HistoricalCountSchema.safeParse(req.query) + if (!paramCheck.success) { + return handleAndReturnErrorResponse(req, res, paramCheck.error) + } + + try { + const { frequency, variant, startAt, endAt } = paramCheck.data + const data = await doGetHistoricalCount( + 'operator', + startAt, + endAt, + frequency, + variant + ) + res.status(200).send({ data }) + } catch (error) { + handleAndReturnErrorResponse(req, res, error) + } +} + +export async function getHistoricalStakerCount(req: Request, res: Response) { + const paramCheck = HistoricalCountSchema.safeParse(req.query) + if (!paramCheck.success) { + return handleAndReturnErrorResponse(req, res, paramCheck.error) + } + + try { + const { frequency, variant, startAt, endAt } = paramCheck.data + const data = await doGetHistoricalCount( + 'staker', startAt, endAt, frequency, @@ -268,30 +311,32 @@ async function doGetHistoricalAvsCount( frequency: string, variant: string ) { - const viemClient = getViemClient() - const chainId = await viemClient.getChainId() - const startDate = new Date(startAt) const endDate = new Date(endAt) - const startBlockNumber = await getBlockNumberFromDate(startDate, chainId) - const endBlockNumber = await getBlockNumberFromDate(endDate, chainId) + const initialTally = await prisma.avs.count({ + where: { + createdAt: { + lt: startDate + } + } + }) const avsData = await prisma.avs.findMany({ where: { - createdAtBlock: { - gte: startBlockNumber, - lte: endBlockNumber + createdAt: { + gte: startDate, + lte: endDate } }, orderBy: { - createdAtBlock: 'asc' + createdAt: 'asc' } }) - let tally = 0 + let tally = initialTally const results: { ts: string; value: number }[] = [] - let currentDate = new Date(startDate) + let currentDate = startDate.getTime() const timeInterval = { @@ -301,27 +346,102 @@ async function doGetHistoricalAvsCount( }[frequency] || 3600000 while (currentDate <= endDate) { - const nextDate = new Date(currentDate.getTime() + timeInterval) - const currentBlockNumber = await getBlockNumberFromDate( - currentDate, - chainId - ) - const nextBlockNumber = await getBlockNumberFromDate(nextDate, chainId) + const nextDate = new Date(currentDate + timeInterval).getTime() const intervalData = avsData.filter( (avs) => - avs.createdAtBlock >= currentBlockNumber && - avs.createdAtBlock < nextBlockNumber + avs.createdAt.getTime() >= currentDate && + avs.createdAt.getTime() < nextDate ) if (variant === 'count') { results.push({ - ts: currentDate.toISOString(), + ts: new Date(Number(currentDate)).toISOString(), value: intervalData.length }) } else { tally += intervalData.length - results.push({ ts: currentDate.toISOString(), value: tally }) + results.push({ + ts: new Date(Number(currentDate)).toISOString(), + value: tally + }) + } + + currentDate = nextDate + } + + return results +} + +async function doGetHistoricalCount( + modelName: 'avs' | 'operator' | 'staker', + startAt: string, + endAt: string, + frequency: string, + variant: string +) { + const startDate = new Date(startAt) + const endDate = new Date(endAt) + + if (!['avs', 'operator', 'staker'].includes(modelName)) { + throw new Error('Invalid model name') + } + + // biomelint/suspicious/noExplicitAny + const model = prisma[modelName] as any + + // Initial tally count + const initialTally = await model.count({ + where: { + createdAt: { + lt: startDate + } + } + }) + + const modelData = await model.findMany({ + where: { + createdAt: { + gte: startDate, + lte: endDate + } + }, + orderBy: { + createdAt: 'asc' + } + }) + + let tally = initialTally + const results: { ts: string; value: number }[] = [] + let currentDate = startDate.getTime() + + const timeInterval = + { + '1h': 3600000, + '1d': 86400000, + '7d': 604800000 + }[frequency] || 3600000 + + while (currentDate <= endDate.getTime()) { + const nextDate = new Date(currentDate + timeInterval).getTime() + + const intervalData = modelData.filter( + (data) => + data.createdAt.getTime() >= currentDate && + data.createdAt.getTime() < nextDate + ) + + if (variant === 'count') { + results.push({ + ts: new Date(Number(currentDate)).toISOString(), + value: intervalData.length + }) + } else { + tally += intervalData.length + results.push({ + ts: new Date(Number(currentDate)).toISOString(), + value: tally + }) } currentDate = nextDate diff --git a/packages/api/src/routes/metrics/metricRoutes.ts b/packages/api/src/routes/metrics/metricRoutes.ts index 26fb5aaa..c8e6ea06 100644 --- a/packages/api/src/routes/metrics/metricRoutes.ts +++ b/packages/api/src/routes/metrics/metricRoutes.ts @@ -8,7 +8,9 @@ import { getTvlBeaconChain, getTvlRestaking, getTvlRestakingByStrategy, - getHistoricalAvsCount + getHistoricalAvsCount, + getHistoricalOperatorCount, + getHistoricalStakerCount } from './metricController' import routeCache from 'route-cache' @@ -37,6 +39,22 @@ router.get('/total-operators', routeCache.cacheSeconds(120), getTotalOperators) router.get('/total-stakers', routeCache.cacheSeconds(120), getTotalStakers) -router.get('/historical/avs', routeCache.cacheSeconds(120), getHistoricalAvsCount) +router.get( + '/historical/avs', + routeCache.cacheSeconds(120), + getHistoricalAvsCount +) + +router.get( + '/historical/operator', + routeCache.cacheSeconds(120), + getHistoricalOperatorCount +) + +router.get( + '/historical/staker', + routeCache.cacheSeconds(120), + getHistoricalStakerCount +) export default router diff --git a/packages/api/src/utils/blockNumber.ts b/packages/api/src/utils/blockNumber.ts deleted file mode 100644 index 711e60fb..00000000 --- a/packages/api/src/utils/blockNumber.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { cacheStore } from 'route-cache' - -export async function getBlockNumberFromDate(date: Date, chainId: number) { - const timestamp = Math.floor(date.getTime() / 1000) - const cacheKey = `block_${timestamp}` - const cachedValue = await cacheStore.get(cacheKey) - - if (cachedValue) { - return cachedValue.height - } - - const response = - chainId === 1 - ? await fetch(`https://coins.llama.fi/block/ethereum/${timestamp}`) - : await fetch(`https://coins.llama.fi/block/holesky/${timestamp}`) - - if (!response.ok) { - throw new Error('Failed to fetch block number from date') - } - - const data = await response.json() - await cacheStore.set(cacheKey, data, 120_000) // Cache for 2 minutes (120,000 milliseconds) - - return data.height -} From 7fa6d21efcb56c4702f56baa5916bb1784358fa7 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Thu, 23 May 2024 14:59:25 +0530 Subject: [PATCH 13/62] removed old count function --- .../src/routes/metrics/metricController.ts | 68 ------------------- 1 file changed, 68 deletions(-) diff --git a/packages/api/src/routes/metrics/metricController.ts b/packages/api/src/routes/metrics/metricController.ts index 23a4d353..58b87099 100644 --- a/packages/api/src/routes/metrics/metricController.ts +++ b/packages/api/src/routes/metrics/metricController.ts @@ -305,74 +305,6 @@ async function doGetTotalStakerCount() { return stakers } -async function doGetHistoricalAvsCount( - startAt: string, - endAt: string, - frequency: string, - variant: string -) { - const startDate = new Date(startAt) - const endDate = new Date(endAt) - - const initialTally = await prisma.avs.count({ - where: { - createdAt: { - lt: startDate - } - } - }) - - const avsData = await prisma.avs.findMany({ - where: { - createdAt: { - gte: startDate, - lte: endDate - } - }, - orderBy: { - createdAt: 'asc' - } - }) - - let tally = initialTally - const results: { ts: string; value: number }[] = [] - let currentDate = startDate.getTime() - - const timeInterval = - { - '1h': 3600000, - '1d': 86400000, - '7d': 604800000 - }[frequency] || 3600000 - - while (currentDate <= endDate) { - const nextDate = new Date(currentDate + timeInterval).getTime() - - const intervalData = avsData.filter( - (avs) => - avs.createdAt.getTime() >= currentDate && - avs.createdAt.getTime() < nextDate - ) - - if (variant === 'count') { - results.push({ - ts: new Date(Number(currentDate)).toISOString(), - value: intervalData.length - }) - } else { - tally += intervalData.length - results.push({ - ts: new Date(Number(currentDate)).toISOString(), - value: tally - }) - } - - currentDate = nextDate - } - - return results -} - async function doGetHistoricalCount( modelName: 'avs' | 'operator' | 'staker', startAt: string, From a81c7508acc9386bdfd55c58d2fa0277d1ff6311 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 24 May 2024 13:20:01 +0530 Subject: [PATCH 14/62] cleanup comments --- packages/api/src/routes/metrics/metricController.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/api/src/routes/metrics/metricController.ts b/packages/api/src/routes/metrics/metricController.ts index 58b87099..f71a8a6f 100644 --- a/packages/api/src/routes/metrics/metricController.ts +++ b/packages/api/src/routes/metrics/metricController.ts @@ -6,7 +6,6 @@ import { strategyAbi } from '../../data/abi/strategy' import { getEigenContracts } from '../../data/address' import { handleAndReturnErrorResponse } from '../../schema/errors' import { getAvsFilterQuery } from '../avs/avsController' -import { getBlockNumberFromDate } from '../../utils/blockNumber' import { fetchStrategyTokenPrices } from '../../utils/tokenPrices' import { getStrategiesWithShareUnderlying } from '../strategies/strategiesController' import { HistoricalCountSchema } from '../../schema/zod/schemas/historicalCountQuery' @@ -319,10 +318,9 @@ async function doGetHistoricalCount( throw new Error('Invalid model name') } - // biomelint/suspicious/noExplicitAny + // biome-ignore lint/suspicious/noExplicitAny: const model = prisma[modelName] as any - // Initial tally count const initialTally = await model.count({ where: { createdAt: { From 51211c052a84325eff89bc17d216ef7141fb0229 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 24 May 2024 22:06:44 +0530 Subject: [PATCH 15/62] merged with dev --- packages/monitor/.env.example | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 packages/monitor/.env.example diff --git a/packages/monitor/.env.example b/packages/monitor/.env.example new file mode 100644 index 00000000..be1955c7 --- /dev/null +++ b/packages/monitor/.env.example @@ -0,0 +1,9 @@ +PORT = 3002 +NETWORK = holesky +NETWORK_CHAIN_RPC_URL = "" +NETWORK_CHAIN_WSS_URL = "" +DATABASE_URL = "" +DIRECT_URL = "" +SLACK_ACCESS_TOKEN = "" +ACCEPTABLE_DELAY_1 = 2000 +ACCEPTABLE_DELAY_2 = 16000 \ No newline at end of file From 83a0461fc3d832f9905bd29cfa992afd63a66715 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Sat, 25 May 2024 01:28:44 +0530 Subject: [PATCH 16/62] set max duration limits for each frequency value --- .../zod/schemas/historicalCountQuery.ts | 81 ++++++++++++------- packages/monitor/.env.example | 9 --- 2 files changed, 53 insertions(+), 37 deletions(-) delete mode 100644 packages/monitor/.env.example diff --git a/packages/api/src/schema/zod/schemas/historicalCountQuery.ts b/packages/api/src/schema/zod/schemas/historicalCountQuery.ts index 6ab234e2..c760d4f1 100644 --- a/packages/api/src/schema/zod/schemas/historicalCountQuery.ts +++ b/packages/api/src/schema/zod/schemas/historicalCountQuery.ts @@ -1,32 +1,57 @@ import z from '..' -export const HistoricalCountSchema = z.object({ - frequency: z - .enum(['1h', '1d', '7d']) - .default('1h') - .describe('Frequency of data points'), - variant: z - .enum(['count', 'cumulative']) - .default('cumulative') - .describe('Type of tally, count or cumulative'), - startAt: z - .string() - .optional() - .describe('Start date in ISO string format') - .refine((val) => !val || !Number.isNaN(Date.parse(val)), { - message: 'Invalid date format' - }) - .default(() => new Date(Date.now() - 86400000).toISOString()) // Default to 1 day ago - .describe('Start date in ISO string format'), - endAt: z - .string() - .optional() - .describe('End date in ISO string format') - .refine((val) => !val || !Number.isNaN(Date.parse(val)), { - message: 'Invalid date format' - }) - .default(() => new Date().toISOString()) // Default to now - .describe('End date in ISO string format') -}) +export const HistoricalCountSchema = z + .object({ + frequency: z + .enum(['1h', '1d', '7d']) + .default('1h') + .describe('Frequency of data points'), + variant: z + .enum(['count', 'cumulative']) + .default('cumulative') + .describe('Type of tally, count or cumulative'), + startAt: z + .string() + .optional() + .describe('Start date in ISO string format') + .refine((val) => !val || !Number.isNaN(Date.parse(val)), { + message: 'Invalid date format' + }) + .default(() => new Date(Date.now() - 86400000).toISOString()) // Default to 1 day ago + .describe('Start date in ISO string format'), + endAt: z + .string() + .optional() + .describe('End date in ISO string format') + .refine((val) => !val || !Number.isNaN(Date.parse(val)), { + message: 'Invalid date format' + }) + .default(() => new Date().toISOString()) // Default to now + .describe('End date in ISO string format') + }) + .refine( + (data) => { + const { frequency, startAt, endAt } = data + const start = new Date(startAt) + const end = new Date(endAt) + const durationMs = end.getTime() - start.getTime() + + if (frequency === '1h' && durationMs > 48 * 60 * 60 * 1000) { + return false + } + if (frequency === '1d' && durationMs > 31 * 24 * 60 * 60 * 1000) { + return false + } + if (frequency === '7d' && durationMs > 365 * 24 * 60 * 60 * 1000) { + return false + } + return true + }, + { + message: + 'Duration between startAt and endAt exceeds the allowed maximum for the selected frequency', + path: ['startAt', 'endAt'] + } + ) export default HistoricalCountSchema diff --git a/packages/monitor/.env.example b/packages/monitor/.env.example deleted file mode 100644 index be1955c7..00000000 --- a/packages/monitor/.env.example +++ /dev/null @@ -1,9 +0,0 @@ -PORT = 3002 -NETWORK = holesky -NETWORK_CHAIN_RPC_URL = "" -NETWORK_CHAIN_WSS_URL = "" -DATABASE_URL = "" -DIRECT_URL = "" -SLACK_ACCESS_TOKEN = "" -ACCEPTABLE_DELAY_1 = 2000 -ACCEPTABLE_DELAY_2 = 16000 \ No newline at end of file From e7704506e41d3423827dbc4500f0bd654b4d82e3 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Sun, 26 May 2024 02:11:35 +0530 Subject: [PATCH 17/62] updated validations, route names & no mins/seconds on timestamps --- .../src/routes/metrics/metricController.ts | 9 ++- .../api/src/routes/metrics/metricRoutes.ts | 4 +- .../zod/schemas/historicalCountQuery.ts | 63 ++++++++++++++++++- 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/packages/api/src/routes/metrics/metricController.ts b/packages/api/src/routes/metrics/metricController.ts index f71a8a6f..264a364b 100644 --- a/packages/api/src/routes/metrics/metricController.ts +++ b/packages/api/src/routes/metrics/metricController.ts @@ -311,8 +311,13 @@ async function doGetHistoricalCount( frequency: string, variant: string ) { - const startDate = new Date(startAt) - const endDate = new Date(endAt) + function resetTime(date: Date) { + date.setUTCMinutes(0, 0, 0) + return date + } + + const startDate = resetTime(new Date(startAt)) + const endDate = resetTime(new Date(endAt)) if (!['avs', 'operator', 'staker'].includes(modelName)) { throw new Error('Invalid model name') diff --git a/packages/api/src/routes/metrics/metricRoutes.ts b/packages/api/src/routes/metrics/metricRoutes.ts index c8e6ea06..430b82d5 100644 --- a/packages/api/src/routes/metrics/metricRoutes.ts +++ b/packages/api/src/routes/metrics/metricRoutes.ts @@ -46,13 +46,13 @@ router.get( ) router.get( - '/historical/operator', + '/historical/operators', routeCache.cacheSeconds(120), getHistoricalOperatorCount ) router.get( - '/historical/staker', + '/historical/stakers', routeCache.cacheSeconds(120), getHistoricalStakerCount ) diff --git a/packages/api/src/schema/zod/schemas/historicalCountQuery.ts b/packages/api/src/schema/zod/schemas/historicalCountQuery.ts index c760d4f1..ffed55de 100644 --- a/packages/api/src/schema/zod/schemas/historicalCountQuery.ts +++ b/packages/api/src/schema/zod/schemas/historicalCountQuery.ts @@ -17,7 +17,7 @@ export const HistoricalCountSchema = z .refine((val) => !val || !Number.isNaN(Date.parse(val)), { message: 'Invalid date format' }) - .default(() => new Date(Date.now() - 86400000).toISOString()) // Default to 1 day ago + .default('') .describe('Start date in ISO string format'), endAt: z .string() @@ -26,9 +26,68 @@ export const HistoricalCountSchema = z .refine((val) => !val || !Number.isNaN(Date.parse(val)), { message: 'Invalid date format' }) - .default(() => new Date().toISOString()) // Default to now + .default('') .describe('End date in ISO string format') }) + .refine( + (data) => { + const { startAt, endAt, frequency } = data + if (!endAt) { + if (startAt) { + const startDate = new Date(startAt) + + if (frequency === '1h') { + const endDate = new Date(startDate.getTime() + 48 * 60 * 60 * 1000) + data.endAt = endDate.toISOString() + } + if (frequency === '1d') { + const endDate = new Date( + startDate.getTime() + 31 * 24 * 60 * 60 * 1000 + ) + data.endAt = endDate.toISOString() + } + if (frequency === '7d') { + const endDate = new Date( + startDate.getTime() + 365 * 24 * 60 * 60 * 1000 + ) + data.endAt = endDate.toISOString() + } + } else { + const endDate = new Date() + data.endAt = endDate.toISOString() + } + } + + if (!startAt) { + const endDate = new Date(data.endAt) + + if (frequency === '1h') { + const startDate = new Date(endDate.getTime() - 48 * 60 * 60 * 1000) + data.startAt = startDate.toISOString() + } + if (frequency === '1d') { + const startDate = new Date( + endDate.getTime() - 31 * 24 * 60 * 60 * 1000 + ) + data.startAt = startDate.toISOString() + } + if (frequency === '7d') { + const startDate = new Date( + endDate.getTime() - 365 * 24 * 60 * 60 * 1000 + ) + data.startAt = startDate.toISOString() + } + } + + const start = new Date(data.startAt) + const end = new Date(data.endAt) + return end.getTime() >= start.getTime() + }, + { + message: 'endAt must be after startAt', + path: ['endAt'] + } + ) .refine( (data) => { const { frequency, startAt, endAt } = data From 553d17c3796a4db0818b5fc8fb0b3aeaae062e97 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Mon, 3 Jun 2024 17:50:39 +0530 Subject: [PATCH 18/62] capture deposit logs --- packages/prisma/schema.prisma | 13 ++- packages/seeder/src/index.ts | 2 + packages/seeder/src/seedDeposits.ts | 151 ++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 packages/seeder/src/seedDeposits.ts diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 884ad847..2067e5a2 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -98,7 +98,7 @@ model Staker { operator Operator? @relation(fields: [operatorAddress], references: [address]) operatorAddress String? - shares StakerStrategyShares[] + shares StakerStrategyShares[] createdAtBlock BigInt @default(0) updatedAtBlock BigInt @default(0) @@ -115,6 +115,17 @@ model StakerStrategyShares { @@id([stakerAddress, strategyAddress]) } +model Deposit { + txHash String @id + staker String + token String + strategy String + shares String + + blockNumber BigInt @default(0) + timestamp DateTime @default(now()) +} + model Pod { address String @id @unique owner String diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 8158e9da..46fa2a98 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -10,6 +10,7 @@ import { seedOperatorShares } from './seedOperatorShares' import { seedValidators } from './seedValidators' import { seedQueuedWithdrawals } from './seedWithdrawalsQueued' import { seedCompletedWithdrawals } from './seedWithdrawalsCompleted' +import { seedDeposits } from './seedDeposits' console.log('Initializing seeder ...') @@ -31,6 +32,7 @@ async function seedEigenDataLoop() { await seedOperatorShares(targetBlock) await seedQueuedWithdrawals(targetBlock) await seedCompletedWithdrawals(targetBlock) + await seedDeposits(targetBlock) } catch (error) { console.log('Failed to seed AVS and Opeartors at:', Date.now()) } diff --git a/packages/seeder/src/seedDeposits.ts b/packages/seeder/src/seedDeposits.ts new file mode 100644 index 00000000..5cbafd13 --- /dev/null +++ b/packages/seeder/src/seedDeposits.ts @@ -0,0 +1,151 @@ +import prisma from '@prisma/client' +import { parseAbiItem } from 'viem' +import { getEigenContracts } from './data/address' +import { getViemClient } from './utils/viemClient' +import { getPrismaClient } from './utils/prismaClient' +import { + baseBlock, + bulkUpdateDbTransactions, + fetchLastSyncBlock, + loopThroughBlocks, + saveLastSyncBlock +} from './utils/seeder' + +const blockSyncKey = 'lastSyncedBlock_deposit' + +interface DepositEntryRecord { + txHash: string + staker: string + token: string + strategy: string + shares: string + blockNumber: bigint + timestamp: Date +} + +/** + * Utility function to seed deposits from Deposit events emmited by StrategyManager + * + * @param fromBlock + * @param toBlock + */ +export async function seedDeposits(toBlock?: bigint, fromBlock?: bigint) { + console.log('Seeding Deposits ...') + + const viemClient = getViemClient() + const prismaClient = getPrismaClient() + const depositList: DepositEntryRecord[] = [] + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKey) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + const logs = await viemClient.getLogs({ + address: getEigenContracts().StrategyManager, + event: parseAbiItem( + 'event Deposit(address staker, address token, address strategy, uint256 shares)' + ), + fromBlock, + toBlock + }) + + for (const l in logs) { + const log = logs[l] + + try { + const blockNumber = BigInt(log.blockNumber) + const block = await viemClient.getBlock({ blockNumber: blockNumber }) + const timestamp = new Date(Number(block.timestamp) * 1000) + + depositList.push({ + txHash: String(log.transactionHash).toLowerCase(), + staker: String(log.args.staker).toLowerCase(), + token: String(log.args.token).toLowerCase(), + strategy: String(log.args.strategy).toLowerCase(), + shares: String(log.args.shares), + blockNumber: blockNumber, + timestamp: timestamp + }) + } catch (error) { + console.log('Failed to seed deposit: ', error) + } + } + + console.log( + `Deposits registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` + ) + }) + + // Prepare db transaction object + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + if (firstBlock === baseBlock) { + dbTransactions.push(prismaClient.deposit.deleteMany()) + + const newDeposit: prisma.Deposit[] = [] + + for (const { + txHash, + staker, + token, + strategy, + shares, + blockNumber, + timestamp + } of depositList) { + newDeposit.push({ + txHash, + staker, + token, + strategy, + shares, + blockNumber, + timestamp + }) + } + + dbTransactions.push( + prismaClient.deposit.createMany({ + data: newDeposit, + skipDuplicates: true + }) + ) + } else { + for (const { + txHash, + staker, + token, + strategy, + shares, + blockNumber, + timestamp + } of depositList) { + dbTransactions.push( + prismaClient.deposit.upsert({ + where: { txHash }, + update: {}, + create: { + txHash, + staker, + token, + strategy, + shares, + blockNumber, + timestamp + } + }) + ) + } + } + + await bulkUpdateDbTransactions(dbTransactions) + + // Storing last synced block + await saveLastSyncBlock(blockSyncKey, lastBlock) + + console.log('Seeded Deposits:', depositList.length) +} From c2238d26570230b3c8d250ceace1e5514dac6a4f Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Mon, 3 Jun 2024 19:05:34 +0530 Subject: [PATCH 19/62] cleaned up schema --- packages/prisma/schema.prisma | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 2067e5a2..b361718d 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -116,14 +116,14 @@ model StakerStrategyShares { } model Deposit { - txHash String @id - staker String + txHash String @id unique + stakerAddress String token String strategy String shares String - blockNumber BigInt @default(0) - timestamp DateTime @default(now()) + createdAtBlock BigInt @default(0) + createdAt DateTime @default(now()) } model Pod { From 0f9583157fddb7ab745539bec09f366722461f9e Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Mon, 3 Jun 2024 20:40:30 +0530 Subject: [PATCH 20/62] added api route for deposits --- .../src/routes/deposits/depositController.ts | 71 +++++++++++++++++++ .../api/src/routes/deposits/depositRoutes.ts | 8 +++ packages/api/src/routes/index.ts | 2 + .../api/src/schema/zod/schemas/deposit.ts | 22 ++++++ packages/prisma/schema.prisma | 6 +- packages/seeder/src/seedDeposits.ts | 56 +++++++-------- 6 files changed, 134 insertions(+), 31 deletions(-) create mode 100644 packages/api/src/routes/deposits/depositController.ts create mode 100644 packages/api/src/routes/deposits/depositRoutes.ts create mode 100644 packages/api/src/schema/zod/schemas/deposit.ts diff --git a/packages/api/src/routes/deposits/depositController.ts b/packages/api/src/routes/deposits/depositController.ts new file mode 100644 index 00000000..4e2df6a4 --- /dev/null +++ b/packages/api/src/routes/deposits/depositController.ts @@ -0,0 +1,71 @@ +import type { Request, Response } from 'express' +import { Prisma } from '@prisma/client' +import prisma from '../../utils/prismaClient' +import { handleAndReturnErrorResponse } from '../../schema/errors' +import { DepositListQuerySchema } from '../../schema/zod/schemas/deposit' +import { PaginationQuerySchema } from '../../schema/zod/schemas/paginationQuery' + +/** + * Route to get a list of all deposits, filtered by stakerAddress, strategyAddress and tokenAddress + * + * @param req + * @param res + */ + +export async function getAllDeposits(req: Request, res: Response) { + // Validate query + const result = DepositListQuerySchema.and(PaginationQuerySchema).safeParse( + req.query + ) + if (!result.success) { + return handleAndReturnErrorResponse(req, res, result.error) + } + + const { stakerAddress, tokenAddress, strategyAddress, skip, take } = + result.data + + try { + const filterQuery: Prisma.DepositWhereInput = {} + + if (stakerAddress) { + filterQuery.stakerAddress = stakerAddress.toLowerCase() + } + + if (tokenAddress) { + filterQuery.tokenAddress = tokenAddress.toLowerCase() + } + + if (strategyAddress) { + filterQuery.strategyAddress = strategyAddress.toLowerCase() + } + + const depositCount = await prisma.deposit.count({ + where: filterQuery + }) + + const depositRecords = await prisma.deposit.findMany({ + where: filterQuery, + skip, + take, + orderBy: { createdAtBlock: 'desc' } + }) + + const data = depositRecords.map((deposit) => { + return { + ...deposit, + createdAtBlock: Number(deposit.createdAtBlock), + } + }) + + res.send({ + data, + meta: { + total: depositCount, + skip, + take + } + }) + } catch (error) { + handleAndReturnErrorResponse(req, res, error) + } +} \ No newline at end of file diff --git a/packages/api/src/routes/deposits/depositRoutes.ts b/packages/api/src/routes/deposits/depositRoutes.ts new file mode 100644 index 00000000..e05cd0e2 --- /dev/null +++ b/packages/api/src/routes/deposits/depositRoutes.ts @@ -0,0 +1,8 @@ +import express from 'express' +import { getAllDeposits } from './depositController' + +const router = express.Router() + +router.get('/', getAllDeposits) + +export default router diff --git a/packages/api/src/routes/index.ts b/packages/api/src/routes/index.ts index 68c60e4b..381c417c 100644 --- a/packages/api/src/routes/index.ts +++ b/packages/api/src/routes/index.ts @@ -5,6 +5,7 @@ import operatorRoutes from './operators/operatorRoutes' import stakerRoutes from './stakers/stakerRoutes' import metricRoutes from './metrics/metricRoutes' import withdrawalRoutes from './withdrawals/withdrawalRoutes' +import depositRoutes from './deposits/depositRoutes' const apiRouter = express.Router() @@ -14,5 +15,6 @@ apiRouter.use('/operators', operatorRoutes) apiRouter.use('/stakers', stakerRoutes) apiRouter.use('/metrics', metricRoutes) apiRouter.use('/withdrawals', withdrawalRoutes) +apiRouter.use('/deposits', depositRoutes) export default apiRouter diff --git a/packages/api/src/schema/zod/schemas/deposit.ts b/packages/api/src/schema/zod/schemas/deposit.ts new file mode 100644 index 00000000..fbcc32dd --- /dev/null +++ b/packages/api/src/schema/zod/schemas/deposit.ts @@ -0,0 +1,22 @@ +import z from '../'; + +export const DepositListQuerySchema = z.object({ + stakerAddress: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') + .optional() + .describe('The address of the staker') + .openapi({ example: '0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd' }), + tokenAddress: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') + .optional() + .describe('The address of the token deposited') + .openapi({ example: '0xe95a203b1a91a908f9b9ce46459d101078c2c3cb' }), + strategyAddress: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') + .optional() + .describe('The contract address of the restaking strategy') + .openapi({ example: '0x0fe4f44bee93503346a3ac9ee5a26b130a5796d6' }), +}); diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index b361718d..1a9a8050 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -116,10 +116,10 @@ model StakerStrategyShares { } model Deposit { - txHash String @id unique + txHash String @id @unique stakerAddress String - token String - strategy String + tokenAddress String + strategyAddress String shares String createdAtBlock BigInt @default(0) diff --git a/packages/seeder/src/seedDeposits.ts b/packages/seeder/src/seedDeposits.ts index 5cbafd13..17eaefa2 100644 --- a/packages/seeder/src/seedDeposits.ts +++ b/packages/seeder/src/seedDeposits.ts @@ -19,8 +19,8 @@ interface DepositEntryRecord { token: string strategy: string shares: string - blockNumber: bigint - timestamp: Date + createdAtBlock: bigint + createdAt: Date } /** @@ -62,12 +62,12 @@ export async function seedDeposits(toBlock?: bigint, fromBlock?: bigint) { depositList.push({ txHash: String(log.transactionHash).toLowerCase(), - staker: String(log.args.staker).toLowerCase(), - token: String(log.args.token).toLowerCase(), - strategy: String(log.args.strategy).toLowerCase(), + stakerAddress: String(log.args.staker).toLowerCase(), + tokenAddress: String(log.args.token).toLowerCase(), + strategyAddress: String(log.args.strategy).toLowerCase(), shares: String(log.args.shares), - blockNumber: blockNumber, - timestamp: timestamp + createdAtBlock: blockNumber, + createdAt: timestamp }) } catch (error) { console.log('Failed to seed deposit: ', error) @@ -90,21 +90,21 @@ export async function seedDeposits(toBlock?: bigint, fromBlock?: bigint) { for (const { txHash, - staker, - token, - strategy, + stakerAddress, + tokenAddress, + strategyAddress, shares, - blockNumber, - timestamp + createdAtBlock, + createdAt } of depositList) { newDeposit.push({ txHash, - staker, - token, - strategy, + stakerAddress, + tokenAddress, + strategyAddress, shares, - blockNumber, - timestamp + createdAtBlock, + createdAt }) } @@ -117,12 +117,12 @@ export async function seedDeposits(toBlock?: bigint, fromBlock?: bigint) { } else { for (const { txHash, - staker, - token, - strategy, + stakerAddress, + tokenAddress, + strategyAddress, shares, - blockNumber, - timestamp + createdAtBlock, + createdAt } of depositList) { dbTransactions.push( prismaClient.deposit.upsert({ @@ -130,12 +130,12 @@ export async function seedDeposits(toBlock?: bigint, fromBlock?: bigint) { update: {}, create: { txHash, - staker, - token, - strategy, + stakerAddress, + tokenAddress, + strategyAddress, shares, - blockNumber, - timestamp + createdAtBlock, + createdAt } }) ) @@ -148,4 +148,4 @@ export async function seedDeposits(toBlock?: bigint, fromBlock?: bigint) { await saveLastSyncBlock(blockSyncKey, lastBlock) console.log('Seeded Deposits:', depositList.length) -} +} \ No newline at end of file From d0d6830547f9aef9759fe188a1561ecd5d7ed90b Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Mon, 3 Jun 2024 20:57:04 +0530 Subject: [PATCH 21/62] added route in stakerRoutes to query deposits of any address --- .../src/routes/deposits/depositController.ts | 4 +- .../src/routes/stakers/stakerController.ts | 43 +++++++++++++++++++ .../api/src/routes/stakers/stakerRoutes.ts | 5 ++- .../api/src/schema/zod/schemas/deposit.ts | 40 ++++++++--------- packages/seeder/src/seedDeposits.ts | 2 +- 5 files changed, 70 insertions(+), 24 deletions(-) diff --git a/packages/api/src/routes/deposits/depositController.ts b/packages/api/src/routes/deposits/depositController.ts index 4e2df6a4..566a6ba7 100644 --- a/packages/api/src/routes/deposits/depositController.ts +++ b/packages/api/src/routes/deposits/depositController.ts @@ -53,7 +53,7 @@ export async function getAllDeposits(req: Request, res: Response) { const data = depositRecords.map((deposit) => { return { ...deposit, - createdAtBlock: Number(deposit.createdAtBlock), + createdAtBlock: Number(deposit.createdAtBlock) } }) @@ -68,4 +68,4 @@ export async function getAllDeposits(req: Request, res: Response) { } catch (error) { handleAndReturnErrorResponse(req, res, error) } -} \ No newline at end of file +} diff --git a/packages/api/src/routes/stakers/stakerController.ts b/packages/api/src/routes/stakers/stakerController.ts index 044080c0..9830697b 100644 --- a/packages/api/src/routes/stakers/stakerController.ts +++ b/packages/api/src/routes/stakers/stakerController.ts @@ -312,3 +312,46 @@ export async function getStakerWithdrawalsCompleted( handleAndReturnErrorResponse(req, res, error) } } + +export async function getStakerDeposits(req: Request, res: Response) { + // Validate query + const result = PaginationQuerySchema.safeParse(req.query) + if (!result.success) { + return handleAndReturnErrorResponse(req, res, result.error) + } + + const { skip, take } = result.data + + try { + const { address } = req.params + const filterQuery = { stakerAddress: address } + + const depositCount = await prisma.deposit.count({ + where: filterQuery + }) + const depositRecords = await prisma.deposit.findMany({ + where: filterQuery, + skip, + take, + orderBy: { createdAtBlock: 'desc' } + }) + + const data = depositRecords.map((deposit) => { + return { + ...deposit, + createdAtBlock: Number(deposit.createdAtBlock) + } + }) + + res.send({ + data, + meta: { + total: depositCount, + skip, + take + } + }) + } catch (error) { + handleAndReturnErrorResponse(req, res, error) + } +} diff --git a/packages/api/src/routes/stakers/stakerRoutes.ts b/packages/api/src/routes/stakers/stakerRoutes.ts index 36becb59..070f788e 100644 --- a/packages/api/src/routes/stakers/stakerRoutes.ts +++ b/packages/api/src/routes/stakers/stakerRoutes.ts @@ -5,7 +5,8 @@ import { getStakerWithdrawals, getStakerWithdrawalsCompleted, getStakerWithdrawalsQueued, - getStakerWithdrawalsWithdrawable + getStakerWithdrawalsWithdrawable, + getStakerDeposits } from './stakerController' const router = express.Router() @@ -22,4 +23,6 @@ router.get( ) router.get('/:address/withdrawals/completed', getStakerWithdrawalsCompleted) +router.get('/:address/deposits', getStakerDeposits) + export default router diff --git a/packages/api/src/schema/zod/schemas/deposit.ts b/packages/api/src/schema/zod/schemas/deposit.ts index fbcc32dd..b9616a93 100644 --- a/packages/api/src/schema/zod/schemas/deposit.ts +++ b/packages/api/src/schema/zod/schemas/deposit.ts @@ -1,22 +1,22 @@ -import z from '../'; +import z from '../' export const DepositListQuerySchema = z.object({ - stakerAddress: z - .string() - .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') - .optional() - .describe('The address of the staker') - .openapi({ example: '0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd' }), - tokenAddress: z - .string() - .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') - .optional() - .describe('The address of the token deposited') - .openapi({ example: '0xe95a203b1a91a908f9b9ce46459d101078c2c3cb' }), - strategyAddress: z - .string() - .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') - .optional() - .describe('The contract address of the restaking strategy') - .openapi({ example: '0x0fe4f44bee93503346a3ac9ee5a26b130a5796d6' }), -}); + stakerAddress: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') + .optional() + .describe('The address of the staker') + .openapi({ example: '0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd' }), + tokenAddress: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') + .optional() + .describe('The address of the token deposited') + .openapi({ example: '0xe95a203b1a91a908f9b9ce46459d101078c2c3cb' }), + strategyAddress: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/, 'Invalid Ethereum address') + .optional() + .describe('The contract address of the restaking strategy') + .openapi({ example: '0x0fe4f44bee93503346a3ac9ee5a26b130a5796d6' }) +}) diff --git a/packages/seeder/src/seedDeposits.ts b/packages/seeder/src/seedDeposits.ts index 17eaefa2..7091ba55 100644 --- a/packages/seeder/src/seedDeposits.ts +++ b/packages/seeder/src/seedDeposits.ts @@ -148,4 +148,4 @@ export async function seedDeposits(toBlock?: bigint, fromBlock?: bigint) { await saveLastSyncBlock(blockSyncKey, lastBlock) console.log('Seeded Deposits:', depositList.length) -} \ No newline at end of file +} From ec831c5430c5a5b96a62dd8c09c922d321888041 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Tue, 4 Jun 2024 03:47:20 +0530 Subject: [PATCH 22/62] Include updated schemas to record raw evm logs and block data --- .../migration.sql | 148 ++++++++++++++++++ packages/prisma/schema.prisma | 142 +++++++++++++++++ 2 files changed, 290 insertions(+) create mode 100644 packages/prisma/migrations/20240603221416_include_raw_evm_logs_data/migration.sql diff --git a/packages/prisma/migrations/20240603221416_include_raw_evm_logs_data/migration.sql b/packages/prisma/migrations/20240603221416_include_raw_evm_logs_data/migration.sql new file mode 100644 index 00000000..c088afaf --- /dev/null +++ b/packages/prisma/migrations/20240603221416_include_raw_evm_logs_data/migration.sql @@ -0,0 +1,148 @@ +-- CreateTable +CREATE TABLE "EventLogs_AVSMetadataURIUpdated" ( + "address" TEXT NOT NULL, + "transactionHash" TEXT NOT NULL, + "transactionIndex" INTEGER NOT NULL, + "blockNumber" BIGINT NOT NULL, + "blockHash" TEXT NOT NULL, + "blockTime" TIMESTAMP(3) NOT NULL, + "avs" TEXT NOT NULL, + "metadataURI" TEXT NOT NULL, + + CONSTRAINT "EventLogs_AVSMetadataURIUpdated_pkey" PRIMARY KEY ("transactionHash","transactionIndex") +); + +-- CreateTable +CREATE TABLE "EventLogs_OperatorMetadataURIUpdated" ( + "address" TEXT NOT NULL, + "transactionHash" TEXT NOT NULL, + "transactionIndex" INTEGER NOT NULL, + "blockNumber" BIGINT NOT NULL, + "blockHash" TEXT NOT NULL, + "blockTime" TIMESTAMP(3) NOT NULL, + "operator" TEXT NOT NULL, + "metadataURI" TEXT NOT NULL, + + CONSTRAINT "EventLogs_OperatorMetadataURIUpdated_pkey" PRIMARY KEY ("transactionHash","transactionIndex") +); + +-- CreateTable +CREATE TABLE "EventLogs_OperatorAVSRegistrationStatusUpdated" ( + "address" TEXT NOT NULL, + "transactionHash" TEXT NOT NULL, + "transactionIndex" INTEGER NOT NULL, + "blockNumber" BIGINT NOT NULL, + "blockHash" TEXT NOT NULL, + "blockTime" TIMESTAMP(3) NOT NULL, + "operator" TEXT NOT NULL, + "avs" TEXT NOT NULL, + "status" INTEGER NOT NULL, + + CONSTRAINT "EventLogs_OperatorAVSRegistrationStatusUpdated_pkey" PRIMARY KEY ("transactionHash","transactionIndex") +); + +-- CreateTable +CREATE TABLE "EventLogs_PodDeployed" ( + "address" TEXT NOT NULL, + "transactionHash" TEXT NOT NULL, + "transactionIndex" INTEGER NOT NULL, + "blockNumber" BIGINT NOT NULL, + "blockHash" TEXT NOT NULL, + "blockTime" TIMESTAMP(3) NOT NULL, + "eigenPod" TEXT NOT NULL, + "podOwner" TEXT NOT NULL, + + CONSTRAINT "EventLogs_PodDeployed_pkey" PRIMARY KEY ("transactionHash","transactionIndex") +); + +-- CreateTable +CREATE TABLE "EventLogs_StakerDelegated" ( + "address" TEXT NOT NULL, + "transactionHash" TEXT NOT NULL, + "transactionIndex" INTEGER NOT NULL, + "blockNumber" BIGINT NOT NULL, + "blockHash" TEXT NOT NULL, + "blockTime" TIMESTAMP(3) NOT NULL, + "staker" TEXT NOT NULL, + "operator" TEXT NOT NULL, + + CONSTRAINT "EventLogs_StakerDelegated_pkey" PRIMARY KEY ("transactionHash","transactionIndex") +); + +-- CreateTable +CREATE TABLE "EventLogs_StakerUndelegated" ( + "address" TEXT NOT NULL, + "transactionHash" TEXT NOT NULL, + "transactionIndex" INTEGER NOT NULL, + "blockNumber" BIGINT NOT NULL, + "blockHash" TEXT NOT NULL, + "blockTime" TIMESTAMP(3) NOT NULL, + "staker" TEXT NOT NULL, + "operator" TEXT NOT NULL, + + CONSTRAINT "EventLogs_StakerUndelegated_pkey" PRIMARY KEY ("transactionHash","transactionIndex") +); + +-- CreateTable +CREATE TABLE "EventLogs_OperatorSharesIncreased" ( + "address" TEXT NOT NULL, + "transactionHash" TEXT NOT NULL, + "transactionIndex" INTEGER NOT NULL, + "blockNumber" BIGINT NOT NULL, + "blockHash" TEXT NOT NULL, + "blockTime" TIMESTAMP(3) NOT NULL, + "staker" TEXT NOT NULL, + "operator" TEXT NOT NULL, + "strategy" TEXT NOT NULL, + "shares" TEXT NOT NULL, + + CONSTRAINT "EventLogs_OperatorSharesIncreased_pkey" PRIMARY KEY ("transactionHash","transactionIndex") +); + +-- CreateTable +CREATE TABLE "EventLogs_OperatorSharesDecreased" ( + "address" TEXT NOT NULL, + "transactionHash" TEXT NOT NULL, + "transactionIndex" INTEGER NOT NULL, + "blockNumber" BIGINT NOT NULL, + "blockHash" TEXT NOT NULL, + "blockTime" TIMESTAMP(3) NOT NULL, + "staker" TEXT NOT NULL, + "operator" TEXT NOT NULL, + "strategy" TEXT NOT NULL, + "shares" TEXT NOT NULL, + + CONSTRAINT "EventLogs_OperatorSharesDecreased_pkey" PRIMARY KEY ("transactionHash","transactionIndex") +); + +-- CreateTable +CREATE TABLE "Evm_BlockData" ( + "number" BIGINT NOT NULL, + "timestamp" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Evm_BlockData_pkey" PRIMARY KEY ("number") +); + +-- CreateIndex +CREATE INDEX "EventLogs_AVSMetadataURIUpdated_avs_idx" ON "EventLogs_AVSMetadataURIUpdated"("avs"); + +-- CreateIndex +CREATE INDEX "EventLogs_OperatorMetadataURIUpdated_operator_idx" ON "EventLogs_OperatorMetadataURIUpdated"("operator"); + +-- CreateIndex +CREATE INDEX "EventLogs_OperatorAVSRegistrationStatusUpdated_operator_avs_idx" ON "EventLogs_OperatorAVSRegistrationStatusUpdated"("operator", "avs"); + +-- CreateIndex +CREATE INDEX "EventLogs_PodDeployed_eigenPod_podOwner_idx" ON "EventLogs_PodDeployed"("eigenPod", "podOwner"); + +-- CreateIndex +CREATE INDEX "EventLogs_StakerDelegated_staker_operator_idx" ON "EventLogs_StakerDelegated"("staker", "operator"); + +-- CreateIndex +CREATE INDEX "EventLogs_StakerUndelegated_staker_operator_idx" ON "EventLogs_StakerUndelegated"("staker", "operator"); + +-- CreateIndex +CREATE INDEX "EventLogs_OperatorSharesIncreased_staker_operator_idx" ON "EventLogs_OperatorSharesIncreased"("staker", "operator"); + +-- CreateIndex +CREATE INDEX "EventLogs_OperatorSharesDecreased_staker_operator_idx" ON "EventLogs_OperatorSharesDecreased"("staker", "operator"); diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 884ad847..6b6b5c8f 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -169,3 +169,145 @@ model Settings { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } + +// RAW Event Logs + +model EventLogs_AVSMetadataURIUpdated { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + avs String + metadataURI String + + @@id([transactionHash, transactionIndex]) + @@index([avs]) +} + +model EventLogs_OperatorMetadataURIUpdated { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + operator String + metadataURI String + + @@id([transactionHash, transactionIndex]) + @@index([operator]) +} + +model EventLogs_OperatorAVSRegistrationStatusUpdated { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + operator String + avs String + status Int + + @@id([transactionHash, transactionIndex]) + @@index([operator, avs]) +} + +model EventLogs_PodDeployed { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + eigenPod String + podOwner String + + @@id([transactionHash, transactionIndex]) + @@index([eigenPod, podOwner]) +} + +model EventLogs_StakerDelegated { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + staker String + operator String + + @@id([transactionHash, transactionIndex]) + @@index([staker, operator]) +} + +model EventLogs_StakerUndelegated { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + staker String + operator String + + @@id([transactionHash, transactionIndex]) + @@index([staker, operator]) +} + +model EventLogs_OperatorSharesIncreased { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + staker String + operator String + strategy String + shares String + + @@id([transactionHash, transactionIndex]) + @@index([staker, operator]) +} + +model EventLogs_OperatorSharesDecreased { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + staker String + operator String + strategy String + shares String + + @@id([transactionHash, transactionIndex]) + @@index([staker, operator]) +} + +// Misc + +model Evm_BlockData { + number BigInt @id + timestamp DateTime +} From 9753cbda9cfc35b72a7fa354550ab3b37a113ae0 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Tue, 4 Jun 2024 21:22:21 +0530 Subject: [PATCH 23/62] added event log seeder and blockData seeder --- packages/seeder/src/events/seedBlockData.ts | 86 +++ packages/seeder/src/events/seedEventLogs.ts | 273 +++++++ packages/seeder/src/index.ts | 24 +- packages/seeder/src/seedAvs.ts | 128 ++-- packages/seeder/src/seedAvsOperators.ts | 43 +- packages/seeder/src/seedOperatorShares.ts | 158 +++-- packages/seeder/src/seedOperators.ts | 129 ++-- packages/seeder/src/seedPods.ts | 61 +- packages/seeder/src/seedStakers.ts | 245 ++++--- packages/seeder/src/utils/events.ts | 750 ++++++++++++++++++++ 10 files changed, 1521 insertions(+), 376 deletions(-) create mode 100644 packages/seeder/src/events/seedBlockData.ts create mode 100644 packages/seeder/src/events/seedEventLogs.ts create mode 100644 packages/seeder/src/utils/events.ts diff --git a/packages/seeder/src/events/seedBlockData.ts b/packages/seeder/src/events/seedBlockData.ts new file mode 100644 index 00000000..c6e03f0c --- /dev/null +++ b/packages/seeder/src/events/seedBlockData.ts @@ -0,0 +1,86 @@ +import prisma from '@prisma/client' +import { getPrismaClient } from '../utils/prismaClient' +import { getViemClient } from '../utils/viemClient' +import { + baseBlock, + bulkUpdateDbTransactions, + fetchLastSyncBlock, + loopThroughBlocks, + saveLastSyncBlock +} from '../utils/seeder' + +const blockSyncKey = 'lastSyncedBlock_blockdata' + +export async function seedBlockData(toBlock?: bigint, fromBlock?: bigint) { + console.log('Seeding Block Data ...') + + const viemClient = getViemClient() + const prismaClient = getPrismaClient() + const blockList: Map = new Map() + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKey) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + let firstBlock = fromBlock + while (firstBlock <= toBlock) { + try { + const blockNumber = firstBlock + const block = await viemClient.getBlock({ blockNumber: blockNumber }) + const timestamp = new Date(Number(block.timestamp) * 1000) + + blockList.set(blockNumber, timestamp) + + firstBlock = firstBlock + 1n + } catch {} + } + console.log(`Block Data added for blocks between ${fromBlock} & ${toBlock}`) + }) + + // Prepare db transaction object + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + if (firstBlock === baseBlock) { + dbTransactions.push(prismaClient.evm_BlockData.deleteMany()) + + const newBlockData: prisma.Evm_BlockData[] = [] + + for (const [number, timestamp] of blockList) { + newBlockData.push({ + number, + timestamp + }) + } + + dbTransactions.push( + prismaClient.evm_BlockData.createMany({ + data: newBlockData, + skipDuplicates: true + }) + ) + } else { + for (const [number, timestamp] of blockList) { + dbTransactions.push( + prismaClient.evm_BlockData.upsert({ + where: { number }, + update: {}, + create: { + number, + timestamp + } + }) + ) + } + } + + await bulkUpdateDbTransactions(dbTransactions) + + // Storing last sycned block + await saveLastSyncBlock(blockSyncKey, lastBlock) + + console.log('Seeded BlockData:', blockList.size) +} diff --git a/packages/seeder/src/events/seedEventLogs.ts b/packages/seeder/src/events/seedEventLogs.ts new file mode 100644 index 00000000..14c15dfd --- /dev/null +++ b/packages/seeder/src/events/seedEventLogs.ts @@ -0,0 +1,273 @@ +import { parseAbiItem } from 'viem' +import { getEigenContracts } from '../data/address' +import { getViemClient } from '../utils/viemClient' +import { + baseBlock, + fetchLastSyncBlock, + loopThroughBlocks, + saveLastSyncBlock +} from '../utils/seeder' +import { + TransactionLog, + AVSMetadataURIUpdatedLog, + OperatorAVSRegistrationStatusUpdatedLog, + OperatorMetadataURIUpdatedLog, + OperatorSharesIncreasedLog, + OperatorSharesDecreasedLog, + PodDeployedLog, + StakerDelegatedLog, + StakerUndelegatedLog, + getBlockDataFromDB, + updateTableAVSMetadataURIUpdated, + updateTableOperatorAVSRegistrationStatusUpdated, + updateTableOperatorMetadataURIUpdated, + updateTableOperatorSharesIncreased, + updateTableOperatorSharesDecreased, + updateTablePodDeployed, + updateTableStakerDelegated, + updateTableStakerUndelegated +} from '../utils/events' + +const blockSyncKey = 'lastSyncedBlock_logs' + +/** + * Utility function to seed avs + * + * @param fromBlock + * @param toBlock + */ +export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { + console.log('Seeding Event Logs ...') + + const viemClient = getViemClient() + + const avsMetadataURIUpdatedList: Map< + TransactionLog, + AVSMetadataURIUpdatedLog + > = new Map() + const operatorAVSRegistrationStatusUpdatedList: Map< + TransactionLog, + OperatorAVSRegistrationStatusUpdatedLog + > = new Map() + const operatorMetadataURIUpdatedList: Map< + TransactionLog, + OperatorMetadataURIUpdatedLog + > = new Map() + const operatorSharesIncreasedList: Map< + TransactionLog, + OperatorSharesIncreasedLog + > = new Map() + const operatorSharesDecreasedList: Map< + TransactionLog, + OperatorSharesDecreasedLog + > = new Map() + const podDeployedList: Map = new Map() + const stakerDelegatedList: Map = new Map() + const stakerUndelegatedList: Map = + new Map() + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKey) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const blockData = await getBlockDataFromDB(firstBlock, lastBlock) + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + try { + const logs = await viemClient.getLogs({ + address: [ + getEigenContracts().AVSDirectory, + getEigenContracts().DelegationManager, + getEigenContracts().EigenPodManager + ], + events: [ + parseAbiItem( + 'event AVSMetadataURIUpdated(address indexed avs, string metadataURI)' + ), + parseAbiItem( + 'event OperatorAVSRegistrationStatusUpdated(address indexed operator, address indexed avs, uint8 status)' + ), + parseAbiItem( + 'event OperatorMetadataURIUpdated(address indexed operator, string metadataURI)' + ), + parseAbiItem( + 'event OperatorSharesIncreased(address indexed operator, address staker, address strategy, uint256 shares)' + ), + parseAbiItem( + 'event OperatorSharesDecreased(address indexed operator, address staker, address strategy, uint256 shares)' + ), + parseAbiItem( + 'event PodDeployed(address indexed eigenPod, address indexed podOwner)' + ), + parseAbiItem( + 'event StakerDelegated(address indexed staker, address indexed operator)' + ), + parseAbiItem( + 'event StakerUndelegated(address indexed staker, address indexed operator)' + ) + ], + fromBlock, + toBlock + }) + + for (const l in logs) { + const log = logs[l] + + const transactionData: TransactionLog = { + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0) + } + + switch (log.eventName) { + case 'AVSMetadataURIUpdated': { + const eventData: AVSMetadataURIUpdatedLog = { + avs: String(log.args.avs).toLowerCase(), + metadataURI: String(log.args.metadataURI).toLowerCase() + } + avsMetadataURIUpdatedList.set(transactionData, eventData) + } + + case 'OperatorAVSRegistrationStatusUpdated': { + const eventData: OperatorAVSRegistrationStatusUpdatedLog = { + operator: String(log.args.operator).toLowerCase(), + avs: String(log.args.avs).toLowerCase(), + status: log.args.status || 0 + } + operatorAVSRegistrationStatusUpdatedList.set( + transactionData, + eventData + ) + } + + case 'OperatorMetadataURIUpdated': { + const eventData: OperatorMetadataURIUpdatedLog = { + operator: String(log.args.operator).toLowerCase(), + metadataURI: String(log.args.metadataURI).toLowerCase() + } + operatorMetadataURIUpdatedList.set(transactionData, eventData) + } + + case 'OperatorSharesIncreased': { + const shares = log.args.shares + if (!shares) continue + + const eventData: OperatorSharesIncreasedLog = { + operator: String(log.args.operator).toLowerCase(), + staker: String(log.args.staker).toLowerCase(), + strategy: String(log.args.strategy).toLowerCase(), + shares: shares.toString() + } + operatorSharesIncreasedList.set(transactionData, eventData) + } + + case 'OperatorSharesDecreased': { + const shares = log.args.shares + if (!shares) continue + + const eventData: OperatorSharesDecreasedLog = { + operator: String(log.args.operator).toLowerCase(), + staker: String(log.args.staker).toLowerCase(), + strategy: String(log.args.strategy).toLowerCase(), + shares: shares.toString() + } + operatorSharesDecreasedList.set(transactionData, eventData) + } + + case 'PodDeployed': { + const eventData: PodDeployedLog = { + eigenPod: String(log.args.eigenPod).toLowerCase(), + podOwner: String(log.args.podOwner).toLowerCase() + } + podDeployedList.set(transactionData, eventData) + } + + case 'StakerDelegated': { + const eventData: StakerDelegatedLog = { + staker: String(log.args.staker).toLowerCase(), + operator: String(log.args.operator).toLowerCase() + } + stakerDelegatedList.set(transactionData, eventData) + } + + case 'StakerUndelegated': { + const eventData: StakerUndelegatedLog = { + staker: String(log.args.staker).toLowerCase(), + operator: String(log.args.operator).toLowerCase() + } + stakerUndelegatedList.set(transactionData, eventData) + } + } + } + console.log( + `Event logs registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` + ) + } catch (error) {} + }) + + // Prepare db transaction object + // biome-ignore lint/suspicious/noExplicitAny: + let dbTransactions: any[] = [] + const flag = firstBlock === baseBlock + + await updateTableAVSMetadataURIUpdated( + dbTransactions, + avsMetadataURIUpdatedList, + flag + ) + await updateTableOperatorAVSRegistrationStatusUpdated( + dbTransactions, + operatorAVSRegistrationStatusUpdatedList, + flag + ) + await updateTableOperatorMetadataURIUpdated( + dbTransactions, + operatorMetadataURIUpdatedList, + flag + ) + await updateTableOperatorSharesIncreased( + dbTransactions, + operatorSharesIncreasedList, + flag + ) + await updateTableOperatorSharesDecreased( + dbTransactions, + operatorSharesDecreasedList, + flag + ) + await updateTablePodDeployed(dbTransactions, podDeployedList, flag) + await updateTableStakerDelegated(dbTransactions, stakerDelegatedList, flag) + await updateTableStakerUndelegated( + dbTransactions, + stakerUndelegatedList, + flag + ) + + // Storing last synced block + await saveLastSyncBlock(blockSyncKey, lastBlock) + + console.log('Seeded AVSMetadataURIUpdated:', avsMetadataURIUpdatedList.size) + console.log( + 'Seeded OperatorAVSRegistrationStatusUpdated:', + operatorAVSRegistrationStatusUpdatedList.size + ) + console.log( + 'Seeded OperatorMetadataURIUpdated:', + operatorMetadataURIUpdatedList.size + ) + console.log( + 'Seeded OperatorSharesIncreased:', + operatorSharesIncreasedList.size + ) + console.log( + 'Seeded OperatorSharesDecreased:', + operatorSharesDecreasedList.size + ) + console.log('Seeded PodDeployed:', podDeployedList.size) + console.log('Seeded StakerDelegated:', stakerDelegatedList.size) + console.log('Seeded StakerUndelegated:', stakerUndelegatedList.size) +} diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 8158e9da..7996da66 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -6,6 +6,8 @@ import { seedOperators } from './seedOperators' import { seedPods } from './seedPods' import { seedStakers } from './seedStakers' import { getViemClient } from './utils/viemClient' +import { seedBlockData } from './events/seedBlockData' +import { seedEventLogs } from './events/seedEventLogs' import { seedOperatorShares } from './seedOperatorShares' import { seedValidators } from './seedValidators' import { seedQueuedWithdrawals } from './seedWithdrawalsQueued' @@ -17,11 +19,30 @@ function delay(seconds: number) { return new Promise((resolve) => setTimeout(resolve, seconds * 1000)) } -async function seedEigenDataLoop() { +async function seedEventLogsLoop() { while (true) { try { const viemClient = getViemClient() const targetBlock = await viemClient.getBlockNumber() + console.log('Seeding Block & Log Data ...', targetBlock) + + await seedBlockData(targetBlock) + await seedEventLogs(targetBlock) + } catch (error) { + console.log('Failed to seed Block and Log Data at:', Date.now()) + console.log(error) + } + + await delay(90) + } +} + +async function seedEigenDataLoop() { + while (true) { + try { + const viemClient = getViemClient() + const targetBlock = await viemClient.getBlockNumber() // TODO: get targetBlock from Settings (lastSyncBlock_logs) + console.log('Seeding Eigen Data ...', targetBlock) await seedAvs(targetBlock) @@ -58,5 +79,6 @@ async function seedEigenPodValidators() { } } +seedEventLogsLoop() seedEigenDataLoop() seedEigenPodValidators() diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index f258fdf0..70faa43d 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -1,15 +1,12 @@ import prisma from '@prisma/client' -import { parseAbiItem } from 'viem' import { isValidMetadataUrl, validateMetadata } from './utils/metadata' import { type EntityMetadata, defaultMetadata } from './utils/metadata' -import { getEigenContracts } from './data/address' import { getViemClient } from './utils/viemClient' import { getPrismaClient } from './utils/prismaClient' import { baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, - loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -41,77 +38,72 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { : await fetchLastSyncBlock(blockSyncKey) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - // Loop through evm logs - await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - const logs = await viemClient.getLogs({ - address: getEigenContracts().AVSDirectory, - event: parseAbiItem( - 'event AVSMetadataURIUpdated(address indexed avs, string metadataURI)' - ), - fromBlock, - toBlock - }) - - for (const l in logs) { - const log = logs[l] - - const avsAddress = String(log.args.avs).toLowerCase() - const existingRecord = avsList.get(avsAddress) - - const blockNumber = BigInt(log.blockNumber) - const block = await viemClient.getBlock({ blockNumber: blockNumber }) - const timestamp = new Date(Number(block.timestamp) * 1000) - - try { - if (log.args.metadataURI && isValidMetadataUrl(log.args.metadataURI)) { - const response = await fetch(log.args.metadataURI) - const data = await response.text() - const avsMetadata = validateMetadata(data) - - if (avsMetadata) { - if (existingRecord) { - // Avs already registered, valid metadata uri - avsList.set(avsAddress, { - metadata: avsMetadata, - createdAtBlock: existingRecord.createdAtBlock, - updatedAtBlock: blockNumber, - createdAt: existingRecord.createdAt, - updatedAt: timestamp - }) - } else { - // Avs not registered, valid metadata uri - avsList.set(avsAddress, { - metadata: avsMetadata, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } + const logs = await prismaClient.eventLogs_AVSMetadataURIUpdated.findMany({ + where: { + blockNumber: { + gte: fromBlock, + lte: toBlock + } + } + }) + + for (const l in logs) { + const log = logs[l] + + const avsAddress = String(log.avs).toLowerCase() + const existingRecord = avsList.get(avsAddress) + + const blockNumber = BigInt(log.blockNumber) + const timestamp = new Date(Number(log.blockTime) * 1000) + + try { + if (log.metadataURI && isValidMetadataUrl(log.metadataURI)) { + const response = await fetch(log.metadataURI) + const data = await response.text() + const avsMetadata = validateMetadata(data) + + if (avsMetadata) { + if (existingRecord) { + // Avs already registered, valid metadata uri + avsList.set(avsAddress, { + metadata: avsMetadata, + createdAtBlock: existingRecord.createdAtBlock, + updatedAtBlock: blockNumber, + createdAt: existingRecord.createdAt, + updatedAt: timestamp + }) } else { - throw new Error('Missing avs metadata') + // Avs not registered, valid metadata uri + avsList.set(avsAddress, { + metadata: avsMetadata, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) } } else { - throw new Error('Invalid avs metadata uri') + throw new Error('Missing avs metadata') } - } catch (error) { - if (!existingRecord) { - // Avs not registered, invalid metadata uri - avsList.set(avsAddress, { - metadata: defaultMetadata, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } // Ignore case where Avs is already registered and is updated with invalid metadata uri + } else { + throw new Error('Invalid avs metadata uri') } + } catch (error) { + if (!existingRecord) { + // Avs not registered, invalid metadata uri + avsList.set(avsAddress, { + metadata: defaultMetadata, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) + } // Ignore case where Avs is already registered and is updated with invalid metadata uri } - - console.log( - `Avs registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` - ) - }) + } + console.log( + `Avs registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` + ) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedAvsOperators.ts b/packages/seeder/src/seedAvsOperators.ts index b6a5b26e..0f0f0ec6 100644 --- a/packages/seeder/src/seedAvsOperators.ts +++ b/packages/seeder/src/seedAvsOperators.ts @@ -1,12 +1,9 @@ -import { parseAbiItem } from 'viem' import { getViemClient } from './utils/viemClient' -import { getEigenContracts } from './data/address' import { getPrismaClient } from './utils/prismaClient' import { baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, - loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -31,34 +28,30 @@ export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { avs.map((a) => avsOperatorsList.set(a.address, new Map())) - // Loop through evm logs - await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - const logs = await viemClient.getLogs({ - address: getEigenContracts().AVSDirectory, - event: parseAbiItem( - 'event OperatorAVSRegistrationStatusUpdated(address indexed operator, address indexed avs, uint8 status)' - ), - fromBlock, - toBlock + const logs = + await prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.findMany({ + where: { + blockNumber: { + gte: fromBlock, + lte: toBlock + } + } }) - for (const l in logs) { - const log = logs[l] + for (const l in logs) { + const log = logs[l] - const avsAddress = String(log.args.avs).toLowerCase() - const operatorAddress = String(log.args.operator).toLowerCase() + const avsAddress = String(log.avs).toLowerCase() + const operatorAddress = String(log.operator).toLowerCase() - if (avsOperatorsList.has(avsAddress)) { - avsOperatorsList - .get(avsAddress) - ?.set(operatorAddress, log.args.status || 0) - } + if (avsOperatorsList.has(avsAddress)) { + avsOperatorsList.get(avsAddress)?.set(operatorAddress, log.status || 0) } + } - console.log( - `Avs operators updated between blocks ${fromBlock} ${toBlock}: ${logs.length}` - ) - }) + console.log( + `Avs operators updated between blocks ${fromBlock} ${toBlock}: ${logs.length}` + ) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedOperatorShares.ts b/packages/seeder/src/seedOperatorShares.ts index 1b2de63e..0d924ce0 100644 --- a/packages/seeder/src/seedOperatorShares.ts +++ b/packages/seeder/src/seedOperatorShares.ts @@ -1,5 +1,3 @@ -import { parseAbiItem } from 'viem' -import { getEigenContracts } from './data/address' import { getViemClient } from './utils/viemClient' import { getPrismaClient } from './utils/prismaClient' import { @@ -7,7 +5,6 @@ import { bulkUpdateDbTransactions, fetchLastSyncBlock, IMap, - loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -32,93 +29,104 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { await prismaClient.operatorStrategyShares.deleteMany() } - // Loop through evm logs - await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - const logs = await viemClient.getLogs({ - address: getEigenContracts().DelegationManager, - events: [ - parseAbiItem( - 'event OperatorSharesIncreased(address indexed operator, address staker, address strategy, uint256 shares)' - ), - parseAbiItem( - 'event OperatorSharesDecreased(address indexed operator, address staker, address strategy, uint256 shares)' - ) - ], - fromBlock, - toBlock - }) - - // Operators list - const operatorAddresses = logs.map((l) => - String(l.args.operator).toLowerCase() - ) + const logsOperatorSharesIncreased = + await prismaClient.eventLogs_OperatorSharesIncreased + .findMany({ + where: { + blockNumber: { + gte: fromBlock, + lte: toBlock + } + } + }) + .then((logs) => + logs.map((log) => ({ ...log, eventName: 'OperatorSharesIncreased' })) + ) + + const logsOperatorSharesDecreased = + await prismaClient.eventLogs_OperatorSharesDecreased + .findMany({ + where: { + blockNumber: { + gte: fromBlock, + lte: toBlock + } + } + }) + .then((logs) => + logs.map((log) => ({ ...log, eventName: 'OperatorSharesDecreased' })) + ) - const operatorInit = await prismaClient.operator.findMany({ - where: { address: { in: operatorAddresses } }, - include: { - shares: true - } - }) + const logs = [...logsOperatorSharesIncreased, ...logsOperatorSharesDecreased] - for (const l in logs) { - const log = logs[l] + // Operators list + const operatorAddresses = logs.map((l) => String(l.operator).toLowerCase()) - const operatorAddress = String(log.args.operator).toLowerCase() - const strategyAddress = String(log.args.strategy).toLowerCase() - const shares = log.args.shares - if (!shares) continue + const operatorInit = await prismaClient.operator.findMany({ + where: { address: { in: operatorAddresses } }, + include: { + shares: true + } + }) - // Load existing staker shares data - if (!operatorShares.has(operatorAddress)) { - const foundOperatorInit = operatorInit.find( - (o) => o.address.toLowerCase() === operatorAddress.toLowerCase() + for (const l in logs) { + const log = logs[l] + + const operatorAddress = String(log.operator).toLowerCase() + const strategyAddress = String(log.strategy).toLowerCase() + const shares = BigInt(log.shares) + if (!shares) continue + + // Load existing staker shares data + if (!operatorShares.has(operatorAddress)) { + const foundOperatorInit = operatorInit.find( + (o) => o.address.toLowerCase() === operatorAddress.toLowerCase() + ) + if (foundOperatorInit) { + operatorShares.set( + operatorAddress, + foundOperatorInit.shares.map((o) => ({ + ...o, + shares: BigInt(o.shares) + })) ) - if (foundOperatorInit) { - operatorShares.set( - operatorAddress, - foundOperatorInit.shares.map((o) => ({ - ...o, - shares: BigInt(o.shares) - })) - ) - } else { - operatorShares.set(operatorAddress, []) - } + } else { + operatorShares.set(operatorAddress, []) } + } + + let foundSharesIndex = operatorShares + .get(operatorAddress) + .findIndex( + (os) => + os.strategyAddress.toLowerCase() === strategyAddress.toLowerCase() + ) + + if (foundSharesIndex !== undefined && foundSharesIndex === -1) { + operatorShares + .get(operatorAddress) + .push({ shares: 0n, strategyAddress: strategyAddress }) - let foundSharesIndex = operatorShares + foundSharesIndex = operatorShares .get(operatorAddress) .findIndex( (os) => os.strategyAddress.toLowerCase() === strategyAddress.toLowerCase() ) + } - if (foundSharesIndex !== undefined && foundSharesIndex === -1) { - operatorShares - .get(operatorAddress) - .push({ shares: 0n, strategyAddress: strategyAddress }) - - foundSharesIndex = operatorShares - .get(operatorAddress) - .findIndex( - (os) => - os.strategyAddress.toLowerCase() === strategyAddress.toLowerCase() - ) - } - - if (log.eventName === 'OperatorSharesIncreased') { - operatorShares.get(operatorAddress)[foundSharesIndex].shares = - operatorShares.get(operatorAddress)[foundSharesIndex].shares + shares - } else if (log.eventName === 'OperatorSharesDecreased') { - operatorShares.get(operatorAddress)[foundSharesIndex].shares = - operatorShares.get(operatorAddress)[foundSharesIndex].shares - shares - } + if (log.eventName === 'OperatorSharesIncreased') { + operatorShares.get(operatorAddress)[foundSharesIndex].shares = + operatorShares.get(operatorAddress)[foundSharesIndex].shares + shares + } else if (log.eventName === 'OperatorSharesDecreased') { + operatorShares.get(operatorAddress)[foundSharesIndex].shares = + operatorShares.get(operatorAddress)[foundSharesIndex].shares - shares } + } - console.log( - `Operator shares updated between blocks ${fromBlock} ${toBlock}: ${logs.length}` - ) - }) + console.log( + `Operator shares updated between blocks ${fromBlock} ${toBlock}: ${logs.length}` + ) // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index eac606fb..41dc7070 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -1,19 +1,16 @@ import prisma from '@prisma/client' import { getPrismaClient } from './utils/prismaClient' -import { parseAbiItem } from 'viem' import { type EntityMetadata, defaultMetadata, isValidMetadataUrl, validateMetadata } from './utils/metadata' -import { getEigenContracts } from './data/address' import { getViemClient } from './utils/viemClient' import { baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, - loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -39,77 +36,75 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { : await fetchLastSyncBlock(blockSyncKey) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - // Loop through evm logs - await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - const logs = await viemClient.getLogs({ - address: getEigenContracts().DelegationManager, - event: parseAbiItem( - 'event OperatorMetadataURIUpdated(address indexed operator, string metadataURI)' - ), - fromBlock, - toBlock - }) - - for (const l in logs) { - const log = logs[l] - - const operatorAddress = String(log.args.operator).toLowerCase() - const existingRecord = operatorList.get(operatorAddress) - - const blockNumber = BigInt(log.blockNumber) - const block = await viemClient.getBlock({ blockNumber: blockNumber }) - const timestamp = new Date(Number(block.timestamp) * 1000) - - try { - if (log.args.metadataURI && isValidMetadataUrl(log.args.metadataURI)) { - const response = await fetch(log.args.metadataURI) - const data = await response.text() - const operatorMetadata = validateMetadata(data) - - if (operatorMetadata) { - if (existingRecord) { - // Operator already registered, valid metadata uri - operatorList.set(operatorAddress, { - metadata: operatorMetadata, - createdAtBlock: existingRecord.createdAtBlock, - updatedAtBlock: blockNumber, - createdAt: existingRecord.createdAt, - updatedAt: timestamp - }) - } else { - // Operator not registered, valid metadata uri - operatorList.set(operatorAddress, { - metadata: operatorMetadata, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } + const logs = await prismaClient.eventLogs_OperatorMetadataURIUpdated.findMany( + { + where: { + blockNumber: { + gte: fromBlock, + lte: toBlock + } + } + } + ) + + for (const l in logs) { + const log = logs[l] + + const operatorAddress = String(log.operator).toLowerCase() + const existingRecord = operatorList.get(operatorAddress) + + const blockNumber = BigInt(log.blockNumber) + const timestamp = new Date(Number(log.blockTime) * 1000) + + try { + if (log.metadataURI && isValidMetadataUrl(log.metadataURI)) { + const response = await fetch(log.metadataURI) + const data = await response.text() + const operatorMetadata = validateMetadata(data) + + if (operatorMetadata) { + if (existingRecord) { + // Operator already registered, valid metadata uri + operatorList.set(operatorAddress, { + metadata: operatorMetadata, + createdAtBlock: existingRecord.createdAtBlock, + updatedAtBlock: blockNumber, + createdAt: existingRecord.createdAt, + updatedAt: timestamp + }) } else { - throw new Error('Missing operator metadata') + // Operator not registered, valid metadata uri + operatorList.set(operatorAddress, { + metadata: operatorMetadata, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) } } else { - throw new Error('Invalid operator metadata uri') + throw new Error('Missing operator metadata') } - } catch (error) { - if (!existingRecord) { - // Operator not registered, invalid metadata uri - operatorList.set(operatorAddress, { - metadata: defaultMetadata, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } // Ignore case where Operator is already registered and is updated with invalid metadata uri + } else { + throw new Error('Invalid operator metadata uri') } + } catch (error) { + if (!existingRecord) { + // Operator not registered, invalid metadata uri + operatorList.set(operatorAddress, { + metadata: defaultMetadata, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) + } // Ignore case where Operator is already registered and is updated with invalid metadata uri } + } - console.log( - `Operators registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` - ) - }) + console.log( + `Operators registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` + ) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index e438f639..6fe4b9d9 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -1,13 +1,10 @@ import prisma from '@prisma/client' -import { parseAbiItem } from 'viem' -import { getEigenContracts } from './data/address' import { getViemClient } from './utils/viemClient' import { getPrismaClient } from './utils/prismaClient' import { baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, - loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -30,42 +27,38 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { : await fetchLastSyncBlock(blockSyncKey) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - // Loop through evm logs - await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - const logs = await viemClient.getLogs({ - address: getEigenContracts().EigenPodManager, - event: parseAbiItem( - 'event PodDeployed(address indexed eigenPod, address indexed podOwner)' - ), - fromBlock, - toBlock - }) + const logs = await prismaClient.eventLogs_PodDeployed.findMany({ + where: { + blockNumber: { + gte: fromBlock, + lte: toBlock + } + } + }) - for (const l in logs) { - const log = logs[l] + for (const l in logs) { + const log = logs[l] - const podAddress = String(log.args.eigenPod).toLowerCase() - const podOwner = String(log.args.podOwner).toLowerCase() + const podAddress = String(log.eigenPod).toLowerCase() + const podOwner = String(log.podOwner).toLowerCase() - const blockNumber = BigInt(log.blockNumber) - const block = await viemClient.getBlock({ blockNumber: blockNumber }) - const timestamp = new Date(Number(block.timestamp) * 1000) + const blockNumber = BigInt(log.blockNumber) + const timestamp = new Date(Number(log.blockTime) * 1000) - podList.push({ - address: podAddress, - owner: podOwner, - blockNumber, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } + podList.push({ + address: podAddress, + owner: podOwner, + blockNumber, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) + } - console.log( - `Pods deployed between blocks ${fromBlock} ${toBlock}: ${logs.length}` - ) - }) + console.log( + `Pods deployed between blocks ${fromBlock} ${toBlock}: ${logs.length}` + ) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index ec14aad6..b7a891c9 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -39,130 +39,163 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { await prismaClient.stakerStrategyShares.deleteMany() } - // Loop through evm logs - await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - // Fetch logs - const logs = await viemClient.getLogs({ - address: getEigenContracts().DelegationManager, - events: [ - parseAbiItem( - 'event StakerDelegated(address indexed staker, address indexed operator)' - ), - parseAbiItem( - 'event StakerUndelegated(address indexed staker, address indexed operator)' - ), - parseAbiItem( - 'event OperatorSharesIncreased(address indexed operator, address staker, address strategy, uint256 shares)' - ), - parseAbiItem( - 'event OperatorSharesDecreased(address indexed operator, address staker, address strategy, uint256 shares)' - ) - ], - fromBlock, - toBlock + const logsStakerDelegated = await prismaClient.eventLogs_StakerDelegated + .findMany({ + where: { + blockNumber: { + gte: fromBlock, + lte: toBlock + } + } }) + .then((logs) => + logs.map((log) => ({ ...log, eventName: 'StakerDelegated' })) + ) - // Stakers list - const stakerAddresses = logs.map((l) => String(l.args.staker).toLowerCase()) - const stakerInit = await prismaClient.staker.findMany({ - where: { address: { in: stakerAddresses } }, - include: { - shares: true + const logsStakerUndelegated = await prismaClient.eventLogs_StakerUndelegated + .findMany({ + where: { + blockNumber: { + gte: fromBlock, + lte: toBlock + } } }) + .then((logs) => + logs.map((log) => ({ ...log, eventName: 'OperatorSharesIncreased' })) + ) - for (const l in logs) { - const log = logs[l] + const logsOperatorSharesIncreased = + await prismaClient.eventLogs_OperatorSharesIncreased + .findMany({ + where: { + blockNumber: { + gte: fromBlock, + lte: toBlock + } + } + }) + .then((logs) => + logs.map((log) => ({ ...log, eventName: 'OperatorSharesDecreased' })) + ) - const operatorAddress = String(log.args.operator).toLowerCase() - const stakerAddress = String(log.args.staker).toLowerCase() + const logsOperatorSharesDecreased = + await prismaClient.eventLogs_OperatorSharesDecreased + .findMany({ + where: { + blockNumber: { + gte: fromBlock, + lte: toBlock + } + } + }) + .then((logs) => + logs.map((log) => ({ ...log, eventName: 'OperatorSharesDecreased' })) + ) - const blockNumber = BigInt(log.blockNumber) - const block = await viemClient.getBlock({ blockNumber: blockNumber }) - const timestamp = new Date(Number(block.timestamp) * 1000) + const logs = [ + ...logsStakerDelegated, + ...logsStakerUndelegated, + ...logsOperatorSharesIncreased, + ...logsOperatorSharesDecreased + ] - // Load existing staker shares data - if (!stakers.has(stakerAddress)) { - const foundStakerInit = stakerInit.find( - (s) => s.address.toLowerCase() === stakerAddress.toLowerCase() - ) - if (foundStakerInit) { - // Address not in this set of logs but in db - stakers.set(stakerAddress, { - operatorAddress: foundStakerInit.operatorAddress, - shares: foundStakerInit.shares.map((s) => ({ - ...s, - shares: BigInt(s.shares) - })), - createdAtBlock: foundStakerInit.createdAtBlock, - updatedAtBlock: blockNumber, - createdAt: foundStakerInit.createdAt, - updatedAt: timestamp - }) - } else { - // Address neither in this set of logs nor in db - stakers.set(stakerAddress, { - operatorAddress: null, - shares: [], - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } + // Stakers list + const stakerAddresses = logs.map((l) => String(l.staker).toLowerCase()) + const stakerInit = await prismaClient.staker.findMany({ + where: { address: { in: stakerAddresses } }, + include: { + shares: true + } + }) + + for (const l in logs) { + const log = logs[l] + + const operatorAddress = String(log.operator).toLowerCase() + const stakerAddress = String(log.staker).toLowerCase() + + const blockNumber = BigInt(log.blockNumber) + const timestamp = new Date(Number(log.blockTime) * 1000) + + // Load existing staker shares data + if (!stakers.has(stakerAddress)) { + const foundStakerInit = stakerInit.find( + (s) => s.address.toLowerCase() === stakerAddress.toLowerCase() + ) + if (foundStakerInit) { + // Address not in this set of logs but in db + stakers.set(stakerAddress, { + operatorAddress: foundStakerInit.operatorAddress, + shares: foundStakerInit.shares.map((s) => ({ + ...s, + shares: BigInt(s.shares) + })), + createdAtBlock: foundStakerInit.createdAtBlock, + updatedAtBlock: blockNumber, + createdAt: foundStakerInit.createdAt, + updatedAt: timestamp + }) } else { - // Address previously found in this set of logs - stakers.get(stakerAddress).updatedAtBlock = blockNumber - stakers.get(stakerAddress).updatedAt = timestamp + // Address neither in this set of logs nor in db + stakers.set(stakerAddress, { + operatorAddress: null, + shares: [], + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) } + } else { + // Address previously found in this set of logs + stakers.get(stakerAddress).updatedAtBlock = blockNumber + stakers.get(stakerAddress).updatedAt = timestamp + } - if (log.eventName === 'StakerDelegated') { - stakers.get(stakerAddress).operatorAddress = operatorAddress - } else if (log.eventName === 'StakerUndelegated') { - stakers.get(stakerAddress).operatorAddress = null - } else if ( - log.eventName === 'OperatorSharesIncreased' || - log.eventName === 'OperatorSharesDecreased' - ) { - const strategyAddress = String(log.args.strategy).toLowerCase() - const shares = log.args.shares - if (!shares) continue - - let foundSharesIndex = stakers + if (log.eventName === 'StakerDelegated') { + stakers.get(stakerAddress).operatorAddress = operatorAddress + } else if (log.eventName === 'StakerUndelegated') { + stakers.get(stakerAddress).operatorAddress = null + } else if ( + log.eventName === 'OperatorSharesIncreased' || + log.eventName === 'OperatorSharesDecreased' + ) { + const strategyAddress = String(log.strategy).toLowerCase() + const shares = BigInt(log.shares) + if (!shares) continue + + let foundSharesIndex = stakers + .get(stakerAddress) + .shares.findIndex( + (ss) => + ss.strategyAddress.toLowerCase() === strategyAddress.toLowerCase() + ) + + if (foundSharesIndex !== undefined && foundSharesIndex === -1) { + stakers.get(stakerAddress).shares.push({ shares: 0n, strategyAddress }) + + foundSharesIndex = stakers .get(stakerAddress) .shares.findIndex( - (ss) => - ss.strategyAddress.toLowerCase() === strategyAddress.toLowerCase() + (os) => + os.strategyAddress.toLowerCase() === strategyAddress.toLowerCase() ) + } - if (foundSharesIndex !== undefined && foundSharesIndex === -1) { - stakers - .get(stakerAddress) - .shares.push({ shares: 0n, strategyAddress }) - - foundSharesIndex = stakers - .get(stakerAddress) - .shares.findIndex( - (os) => - os.strategyAddress.toLowerCase() === - strategyAddress.toLowerCase() - ) - } - - if (log.eventName === 'OperatorSharesIncreased') { - stakers.get(stakerAddress).shares[foundSharesIndex].shares = - stakers.get(stakerAddress).shares[foundSharesIndex].shares + shares - } else if (log.eventName === 'OperatorSharesDecreased') { - stakers.get(stakerAddress).shares[foundSharesIndex].shares = - stakers.get(stakerAddress).shares[foundSharesIndex].shares - shares - } + if (log.eventName === 'OperatorSharesIncreased') { + stakers.get(stakerAddress).shares[foundSharesIndex].shares = + stakers.get(stakerAddress).shares[foundSharesIndex].shares + shares + } else if (log.eventName === 'OperatorSharesDecreased') { + stakers.get(stakerAddress).shares[foundSharesIndex].shares = + stakers.get(stakerAddress).shares[foundSharesIndex].shares - shares } } + } - console.log( - `Stakers deployed between blocks ${fromBlock} ${toBlock}: ${logs.length}` - ) - }) + console.log( + `Stakers deployed between blocks ${fromBlock} ${toBlock}: ${logs.length}` + ) // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] diff --git a/packages/seeder/src/utils/events.ts b/packages/seeder/src/utils/events.ts new file mode 100644 index 00000000..09581c00 --- /dev/null +++ b/packages/seeder/src/utils/events.ts @@ -0,0 +1,750 @@ +import prisma from '@prisma/client' +import { getPrismaClient } from '../utils/prismaClient' +import { bulkUpdateDbTransactions } from '../utils/seeder' + +const prismaClient = getPrismaClient() + +export interface TransactionLog { + address: string + transactionHash: string + transactionIndex: number + blockNumber: bigint + blockHash: string + blockTime: Date +} + +export interface AVSMetadataURIUpdatedLog { + avs: string + metadataURI: string +} + +export interface OperatorAVSRegistrationStatusUpdatedLog { + operator: string + avs: string + status: number +} + +export interface OperatorMetadataURIUpdatedLog { + operator: string + metadataURI: string +} + +export interface OperatorSharesIncreasedLog { + operator: string + staker: string + strategy: string + shares: string +} + +export interface OperatorSharesDecreasedLog { + operator: string + staker: string + strategy: string + shares: string +} + +export interface PodDeployedLog { + eigenPod: string + podOwner: string +} + +export interface StakerDelegatedLog { + staker: string + operator: string +} + +export interface StakerUndelegatedLog { + staker: string + operator: string +} + +export async function updateTableAVSMetadataURIUpdated( + dbTransactions: any[], + avsMetadataURIUpdatedList: Map, + dropTable: boolean = false +) { + try { + if (dropTable) { + dbTransactions.push( + prismaClient.eventLogs_AVSMetadataURIUpdated.deleteMany() + ) + + const newAvsMetadataURIUpdated: prisma.EventLogs_AVSMetadataURIUpdated[] = + [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { avs, metadataURI } + ] of avsMetadataURIUpdatedList) { + newAvsMetadataURIUpdated.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + avs, + metadataURI + }) + } + + dbTransactions.push( + prismaClient.eventLogs_AVSMetadataURIUpdated.createMany({ + data: newAvsMetadataURIUpdated, + skipDuplicates: true + }) + ) + } else { + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { avs, metadataURI } + ] of avsMetadataURIUpdatedList) { + dbTransactions.push( + prismaClient.eventLogs_AVSMetadataURIUpdated.upsert({ + where: { + transactionHash_transactionIndex: { + transactionHash: transactionHash, + transactionIndex: transactionIndex + } + }, + update: {}, + create: { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + avs, + metadataURI + } + }) + ) + } + } + } catch {} + + await bulkUpdateDbTransactions(dbTransactions) +} + +export async function updateTableOperatorAVSRegistrationStatusUpdated( + dbTransactions: any[], + operatorAVSRegistrationStatusUpdatedList: Map< + TransactionLog, + OperatorAVSRegistrationStatusUpdatedLog + >, + dropTable: boolean = false +) { + try { + if (dropTable) { + dbTransactions.push( + prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.deleteMany() + ) + + const newOperatorAVSRegistrationStatusUpdated: prisma.EventLogs_OperatorAVSRegistrationStatusUpdated[] = + [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, avs, status } + ] of operatorAVSRegistrationStatusUpdatedList) { + newOperatorAVSRegistrationStatusUpdated.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + avs, + status + }) + } + + dbTransactions.push( + prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.createMany({ + data: newOperatorAVSRegistrationStatusUpdated, + skipDuplicates: true + }) + ) + } else { + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, avs, status } + ] of operatorAVSRegistrationStatusUpdatedList) { + dbTransactions.push( + prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.upsert({ + where: { + transactionHash_transactionIndex: { + transactionHash: transactionHash, + transactionIndex: transactionIndex + } + }, + update: {}, + create: { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + avs, + status + } + }) + ) + } + } + } catch {} + + await bulkUpdateDbTransactions(dbTransactions) +} + +export async function updateTableOperatorMetadataURIUpdated( + dbTransactions: any[], + operatorMetadataURIUpdatedList: Map< + TransactionLog, + OperatorMetadataURIUpdatedLog + >, + dropTable: boolean = false +) { + try { + if (dropTable) { + dbTransactions.push( + prismaClient.eventLogs_OperatorMetadataURIUpdated.deleteMany() + ) + + const newOperatorMetadataURIUpdated: prisma.EventLogs_OperatorMetadataURIUpdated[] = + [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, metadataURI } + ] of operatorMetadataURIUpdatedList) { + newOperatorMetadataURIUpdated.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + metadataURI + }) + } + + dbTransactions.push( + prismaClient.eventLogs_OperatorMetadataURIUpdated.createMany({ + data: newOperatorMetadataURIUpdated, + skipDuplicates: true + }) + ) + } else { + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, metadataURI } + ] of operatorMetadataURIUpdatedList) { + dbTransactions.push( + prismaClient.eventLogs_OperatorMetadataURIUpdated.upsert({ + where: { + transactionHash_transactionIndex: { + transactionHash: transactionHash, + transactionIndex: transactionIndex + } + }, + update: {}, + create: { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + metadataURI + } + }) + ) + } + } + } catch {} + + await bulkUpdateDbTransactions(dbTransactions) +} + +export async function updateTableOperatorSharesIncreased( + dbTransactions: any[], + operatorSharesIncreasedList: Map, + dropTable: boolean = false +) { + try { + if (dropTable) { + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesIncreased.deleteMany() + ) + + const newOperatorSharesIncreased: prisma.EventLogs_OperatorSharesIncreased[] = + [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, staker, strategy, shares } + ] of operatorSharesIncreasedList) { + newOperatorSharesIncreased.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + staker, + strategy, + shares + }) + } + + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesIncreased.createMany({ + data: newOperatorSharesIncreased, + skipDuplicates: true + }) + ) + } else { + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, staker, strategy, shares } + ] of operatorSharesIncreasedList) { + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesIncreased.upsert({ + where: { + transactionHash_transactionIndex: { + transactionHash: transactionHash, + transactionIndex: transactionIndex + } + }, + update: {}, + create: { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + staker, + strategy, + shares + } + }) + ) + } + } + } catch {} + + await bulkUpdateDbTransactions(dbTransactions) +} + +export async function updateTableOperatorSharesDecreased( + dbTransactions: any[], + operatorSharesDecreasedList: Map, + dropTable: boolean = false +) { + try { + if (dropTable) { + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesDecreased.deleteMany() + ) + + const newOperatorSharesDecreased: prisma.EventLogs_OperatorSharesDecreased[] = + [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, staker, strategy, shares } + ] of operatorSharesDecreasedList) { + newOperatorSharesDecreased.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + staker, + strategy, + shares + }) + } + + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesDecreased.createMany({ + data: newOperatorSharesDecreased, + skipDuplicates: true + }) + ) + } else { + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, staker, strategy, shares } + ] of operatorSharesDecreasedList) { + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesDecreased.upsert({ + where: { + transactionHash_transactionIndex: { + transactionHash: transactionHash, + transactionIndex: transactionIndex + } + }, + update: {}, + create: { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + staker, + strategy, + shares + } + }) + ) + } + } + } catch {} + + await bulkUpdateDbTransactions(dbTransactions) +} + +export async function updateTablePodDeployed( + dbTransactions: any[], + podDeployedList: Map, + dropTable: boolean = false +) { + try { + if (dropTable) { + dbTransactions.push(prismaClient.eventLogs_PodDeployed.deleteMany()) + + const newPodDeployed: prisma.EventLogs_PodDeployed[] = [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { eigenPod, podOwner } + ] of podDeployedList) { + newPodDeployed.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + eigenPod, + podOwner + }) + } + + dbTransactions.push( + prismaClient.eventLogs_PodDeployed.createMany({ + data: newPodDeployed, + skipDuplicates: true + }) + ) + } else { + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { eigenPod, podOwner } + ] of podDeployedList) { + dbTransactions.push( + prismaClient.eventLogs_PodDeployed.upsert({ + where: { + transactionHash_transactionIndex: { + transactionHash: transactionHash, + transactionIndex: transactionIndex + } + }, + update: {}, + create: { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + eigenPod, + podOwner + } + }) + ) + } + } + } catch {} + + await bulkUpdateDbTransactions(dbTransactions) +} + +export async function updateTableStakerDelegated( + dbTransactions: any[], + stakerDelegatedList: Map, + dropTable: boolean = false +) { + try { + if (dropTable) { + dbTransactions.push(prismaClient.eventLogs_StakerDelegated.deleteMany()) + + const newStakerDelegated: prisma.EventLogs_StakerDelegated[] = [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { staker, operator } + ] of stakerDelegatedList) { + newStakerDelegated.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + staker, + operator + }) + } + + dbTransactions.push( + prismaClient.eventLogs_StakerDelegated.createMany({ + data: newStakerDelegated, + skipDuplicates: true + }) + ) + } else { + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { staker, operator } + ] of stakerDelegatedList) { + dbTransactions.push( + prismaClient.eventLogs_StakerDelegated.upsert({ + where: { + transactionHash_transactionIndex: { + transactionHash: transactionHash, + transactionIndex: transactionIndex + } + }, + update: {}, + create: { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + staker, + operator + } + }) + ) + } + } + } catch {} + + await bulkUpdateDbTransactions(dbTransactions) +} + +export async function updateTableStakerUndelegated( + dbTransactions: any[], + stakerUndelegatedList: Map, + dropTable: boolean = false +) { + try { + if (dropTable) { + dbTransactions.push(prismaClient.eventLogs_StakerUndelegated.deleteMany()) + + const newStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { staker, operator } + ] of stakerUndelegatedList) { + newStakerUndelegated.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + staker, + operator + }) + } + + dbTransactions.push( + prismaClient.eventLogs_StakerUndelegated.createMany({ + data: newStakerUndelegated, + skipDuplicates: true + }) + ) + } else { + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { staker, operator } + ] of stakerUndelegatedList) { + dbTransactions.push( + prismaClient.eventLogs_StakerUndelegated.upsert({ + where: { + transactionHash_transactionIndex: { + transactionHash: transactionHash, + transactionIndex: transactionIndex + } + }, + update: {}, + create: { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + staker, + operator + } + }) + ) + } + } + } catch {} + + await bulkUpdateDbTransactions(dbTransactions) +} + +export async function getBlockDataFromDB(fromBlock: bigint, toBlock: bigint) { + const blockData = await prismaClient.evm_BlockData.findMany({ + where: { + number: { + gte: BigInt(fromBlock), + lte: BigInt(toBlock) + } + }, + select: { + number: true, + timestamp: true + }, + orderBy: { + number: 'asc' + } + }) + + return new Map(blockData.map((block) => [block.number, block.timestamp])) +} From 3cf3343c9bb3535501a49539ac9e5feab697eed5 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Wed, 5 Jun 2024 08:38:13 +0530 Subject: [PATCH 24/62] add comments --- packages/seeder/src/events/seedEventLogs.ts | 9 +++--- packages/seeder/src/utils/events.ts | 32 ++++++++++----------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/packages/seeder/src/events/seedEventLogs.ts b/packages/seeder/src/events/seedEventLogs.ts index 14c15dfd..ede37140 100644 --- a/packages/seeder/src/events/seedEventLogs.ts +++ b/packages/seeder/src/events/seedEventLogs.ts @@ -31,7 +31,7 @@ import { const blockSyncKey = 'lastSyncedBlock_logs' /** - * Utility function to seed avs + * Utility function to seed logs for 8 events * * @param fromBlock * @param toBlock @@ -72,7 +72,7 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDB(firstBlock, lastBlock) - // Loop through evm logs + // Loop through evm logs for all 8 events from 3 contracts await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { const logs = await viemClient.getLogs({ @@ -111,6 +111,7 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { toBlock }) + // For each event, setup different lists containing event data for (const l in logs) { const log = logs[l] @@ -209,7 +210,7 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { } catch (error) {} }) - // Prepare db transaction object + // Update all EventLog tables with the respective event log data // biome-ignore lint/suspicious/noExplicitAny: let dbTransactions: any[] = [] const flag = firstBlock === baseBlock @@ -247,7 +248,7 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { flag ) - // Storing last synced block + // Store last synced block await saveLastSyncBlock(blockSyncKey, lastBlock) console.log('Seeded AVSMetadataURIUpdated:', avsMetadataURIUpdatedList.size) diff --git a/packages/seeder/src/utils/events.ts b/packages/seeder/src/utils/events.ts index 09581c00..0ef08ebf 100644 --- a/packages/seeder/src/utils/events.ts +++ b/packages/seeder/src/utils/events.ts @@ -61,10 +61,10 @@ export interface StakerUndelegatedLog { export async function updateTableAVSMetadataURIUpdated( dbTransactions: any[], avsMetadataURIUpdatedList: Map, - dropTable: boolean = false + deleteAll: boolean = false ) { try { - if (dropTable) { + if (deleteAll) { dbTransactions.push( prismaClient.eventLogs_AVSMetadataURIUpdated.deleteMany() ) @@ -147,10 +147,10 @@ export async function updateTableOperatorAVSRegistrationStatusUpdated( TransactionLog, OperatorAVSRegistrationStatusUpdatedLog >, - dropTable: boolean = false + deleteAll: boolean = false ) { try { - if (dropTable) { + if (deleteAll) { dbTransactions.push( prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.deleteMany() ) @@ -235,10 +235,10 @@ export async function updateTableOperatorMetadataURIUpdated( TransactionLog, OperatorMetadataURIUpdatedLog >, - dropTable: boolean = false + deleteAll: boolean = false ) { try { - if (dropTable) { + if (deleteAll) { dbTransactions.push( prismaClient.eventLogs_OperatorMetadataURIUpdated.deleteMany() ) @@ -318,10 +318,10 @@ export async function updateTableOperatorMetadataURIUpdated( export async function updateTableOperatorSharesIncreased( dbTransactions: any[], operatorSharesIncreasedList: Map, - dropTable: boolean = false + deleteAll: boolean = false ) { try { - if (dropTable) { + if (deleteAll) { dbTransactions.push( prismaClient.eventLogs_OperatorSharesIncreased.deleteMany() ) @@ -405,10 +405,10 @@ export async function updateTableOperatorSharesIncreased( export async function updateTableOperatorSharesDecreased( dbTransactions: any[], operatorSharesDecreasedList: Map, - dropTable: boolean = false + deleteAll: boolean = false ) { try { - if (dropTable) { + if (deleteAll) { dbTransactions.push( prismaClient.eventLogs_OperatorSharesDecreased.deleteMany() ) @@ -492,10 +492,10 @@ export async function updateTableOperatorSharesDecreased( export async function updateTablePodDeployed( dbTransactions: any[], podDeployedList: Map, - dropTable: boolean = false + deleteAll: boolean = false ) { try { - if (dropTable) { + if (deleteAll) { dbTransactions.push(prismaClient.eventLogs_PodDeployed.deleteMany()) const newPodDeployed: prisma.EventLogs_PodDeployed[] = [] @@ -572,10 +572,10 @@ export async function updateTablePodDeployed( export async function updateTableStakerDelegated( dbTransactions: any[], stakerDelegatedList: Map, - dropTable: boolean = false + deleteAll: boolean = false ) { try { - if (dropTable) { + if (deleteAll) { dbTransactions.push(prismaClient.eventLogs_StakerDelegated.deleteMany()) const newStakerDelegated: prisma.EventLogs_StakerDelegated[] = [] @@ -652,10 +652,10 @@ export async function updateTableStakerDelegated( export async function updateTableStakerUndelegated( dbTransactions: any[], stakerUndelegatedList: Map, - dropTable: boolean = false + deleteAll: boolean = false ) { try { - if (dropTable) { + if (deleteAll) { dbTransactions.push(prismaClient.eventLogs_StakerUndelegated.deleteMany()) const newStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] From 06aca80cd9d4d2581550202486f75c49656071a4 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Wed, 5 Jun 2024 15:06:47 +0530 Subject: [PATCH 25/62] batched block data request and fixed bugs --- packages/seeder/src/events/seedBlockData.ts | 38 ++++++++++++++------- packages/seeder/src/events/seedEventLogs.ts | 18 +++++----- packages/seeder/src/index.ts | 23 +++++++++---- packages/seeder/src/seedAvs.ts | 8 ++--- packages/seeder/src/seedAvsOperators.ts | 4 +-- packages/seeder/src/seedOperatorShares.ts | 18 +++++----- packages/seeder/src/seedOperators.ts | 10 +++--- packages/seeder/src/seedPods.ts | 6 ++-- packages/seeder/src/seedStakers.ts | 26 +++++++------- 9 files changed, 90 insertions(+), 61 deletions(-) diff --git a/packages/seeder/src/events/seedBlockData.ts b/packages/seeder/src/events/seedBlockData.ts index c6e03f0c..c496c4e4 100644 --- a/packages/seeder/src/events/seedBlockData.ts +++ b/packages/seeder/src/events/seedBlockData.ts @@ -1,4 +1,4 @@ -import prisma from '@prisma/client' +import type prisma from '@prisma/client' import { getPrismaClient } from '../utils/prismaClient' import { getViemClient } from '../utils/viemClient' import { @@ -23,21 +23,35 @@ export async function seedBlockData(toBlock?: bigint, fromBlock?: bigint) { : await fetchLastSyncBlock(blockSyncKey) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - // Loop through evm logs + // Retrieve blocks in batches and extract timestamps await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - let firstBlock = fromBlock - while (firstBlock <= toBlock) { - try { - const blockNumber = firstBlock - const block = await viemClient.getBlock({ blockNumber: blockNumber }) - const timestamp = new Date(Number(block.timestamp) * 1000) + let currentBlock = fromBlock + + while (currentBlock <= toBlock) { + const lastBlockInBatch = currentBlock + 98n // Batches of 99 + const effectiveLastBlock = + lastBlockInBatch > toBlock ? toBlock : lastBlockInBatch - blockList.set(blockNumber, timestamp) + // biome-ignore lint/suspicious/noExplicitAny: + const promises: any[] = [] + for ( + let blockNumber = currentBlock; + blockNumber <= effectiveLastBlock; + blockNumber++ + ) { + promises.push(viemClient.getBlock({ blockNumber: blockNumber })) + } + const blocks = await Promise.all(promises) + for (const block of blocks) { + const timestamp = new Date(Number(block.timestamp) * 1000) + blockList.set(block.number, timestamp) + } - firstBlock = firstBlock + 1n - } catch {} + console.log( + `Retrieved Block Data for ${currentBlock} - ${effectiveLastBlock}` + ) + currentBlock = effectiveLastBlock + 1n } - console.log(`Block Data added for blocks between ${fromBlock} & ${toBlock}`) }) // Prepare db transaction object diff --git a/packages/seeder/src/events/seedEventLogs.ts b/packages/seeder/src/events/seedEventLogs.ts index ede37140..1ada7483 100644 --- a/packages/seeder/src/events/seedEventLogs.ts +++ b/packages/seeder/src/events/seedEventLogs.ts @@ -8,15 +8,15 @@ import { saveLastSyncBlock } from '../utils/seeder' import { - TransactionLog, - AVSMetadataURIUpdatedLog, - OperatorAVSRegistrationStatusUpdatedLog, - OperatorMetadataURIUpdatedLog, - OperatorSharesIncreasedLog, - OperatorSharesDecreasedLog, - PodDeployedLog, - StakerDelegatedLog, - StakerUndelegatedLog, + type TransactionLog, + type AVSMetadataURIUpdatedLog, + type OperatorAVSRegistrationStatusUpdatedLog, + type OperatorMetadataURIUpdatedLog, + type OperatorSharesIncreasedLog, + type OperatorSharesDecreasedLog, + type PodDeployedLog, + type StakerDelegatedLog, + type StakerUndelegatedLog, getBlockDataFromDB, updateTableAVSMetadataURIUpdated, updateTableOperatorAVSRegistrationStatusUpdated, diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 7996da66..1242f348 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -12,9 +12,12 @@ import { seedOperatorShares } from './seedOperatorShares' import { seedValidators } from './seedValidators' import { seedQueuedWithdrawals } from './seedWithdrawalsQueued' import { seedCompletedWithdrawals } from './seedWithdrawalsCompleted' +import { fetchLastSyncBlock } from './utils/seeder' console.log('Initializing seeder ...') +const blockSyncKey = 'lastSyncedBlock_logs' + function delay(seconds: number) { return new Promise((resolve) => setTimeout(resolve, seconds * 1000)) } @@ -24,7 +27,7 @@ async function seedEventLogsLoop() { try { const viemClient = getViemClient() const targetBlock = await viemClient.getBlockNumber() - console.log('Seeding Block & Log Data ...', targetBlock) + console.log('Seeding Block and Log Data ...', targetBlock) await seedBlockData(targetBlock) await seedEventLogs(targetBlock) @@ -33,15 +36,18 @@ async function seedEventLogsLoop() { console.log(error) } - await delay(90) + await delay(90) // Wait for 1.5 minutes (90 seconds) } } async function seedEigenDataLoop() { while (true) { try { - const viemClient = getViemClient() - const targetBlock = await viemClient.getBlockNumber() // TODO: get targetBlock from Settings (lastSyncBlock_logs) + const targetBlock = await fetchLastSyncBlock(blockSyncKey) + if (targetBlock <= 1159609n) { + delay(60) + continue + } console.log('Seeding Eigen Data ...', targetBlock) @@ -54,6 +60,7 @@ async function seedEigenDataLoop() { await seedCompletedWithdrawals(targetBlock) } catch (error) { console.log('Failed to seed AVS and Opeartors at:', Date.now()) + console.log(error) } await delay(120) // Wait for 2 minutes (120 seconds) @@ -65,8 +72,12 @@ async function seedEigenPodValidators() { while (true) { try { - const viemClient = getViemClient() - const targetBlock = await viemClient.getBlockNumber() + const targetBlock = await fetchLastSyncBlock(blockSyncKey) + if (!targetBlock) { + delay(60) + continue + } + console.log('Seeding Eigen Pods Data ...', targetBlock) await seedPods(targetBlock) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 70faa43d..346dacc4 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -41,8 +41,8 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const logs = await prismaClient.eventLogs_AVSMetadataURIUpdated.findMany({ where: { blockNumber: { - gte: fromBlock, - lte: toBlock + gte: firstBlock, + lte: lastBlock } } }) @@ -54,7 +54,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const existingRecord = avsList.get(avsAddress) const blockNumber = BigInt(log.blockNumber) - const timestamp = new Date(Number(log.blockTime) * 1000) + const timestamp = log.blockTime try { if (log.metadataURI && isValidMetadataUrl(log.metadataURI)) { @@ -102,7 +102,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { } } console.log( - `Avs registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` + `Avs registered between blocks ${firstBlock} ${lastBlock}: ${logs.length}` ) // Prepare db transaction object diff --git a/packages/seeder/src/seedAvsOperators.ts b/packages/seeder/src/seedAvsOperators.ts index 0f0f0ec6..d2ae9f9b 100644 --- a/packages/seeder/src/seedAvsOperators.ts +++ b/packages/seeder/src/seedAvsOperators.ts @@ -32,8 +32,8 @@ export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { await prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.findMany({ where: { blockNumber: { - gte: fromBlock, - lte: toBlock + gte: firstBlock, + lte: lastBlock } } }) diff --git a/packages/seeder/src/seedOperatorShares.ts b/packages/seeder/src/seedOperatorShares.ts index 0d924ce0..8721979f 100644 --- a/packages/seeder/src/seedOperatorShares.ts +++ b/packages/seeder/src/seedOperatorShares.ts @@ -4,7 +4,7 @@ import { baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, - IMap, + type IMap, saveLastSyncBlock } from './utils/seeder' @@ -34,8 +34,8 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: fromBlock, - lte: toBlock + gte: firstBlock, + lte: lastBlock } } }) @@ -48,8 +48,8 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: fromBlock, - lte: toBlock + gte: firstBlock, + lte: lastBlock } } }) @@ -74,7 +74,7 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { const operatorAddress = String(log.operator).toLowerCase() const strategyAddress = String(log.strategy).toLowerCase() - const shares = BigInt(log.shares) + const shares = log.shares if (!shares) continue // Load existing staker shares data @@ -117,10 +117,12 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { if (log.eventName === 'OperatorSharesIncreased') { operatorShares.get(operatorAddress)[foundSharesIndex].shares = - operatorShares.get(operatorAddress)[foundSharesIndex].shares + shares + operatorShares.get(operatorAddress)[foundSharesIndex].shares + + BigInt(shares) } else if (log.eventName === 'OperatorSharesDecreased') { operatorShares.get(operatorAddress)[foundSharesIndex].shares = - operatorShares.get(operatorAddress)[foundSharesIndex].shares - shares + operatorShares.get(operatorAddress)[foundSharesIndex].shares - + BigInt(shares) } } diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index 41dc7070..bd500760 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -1,4 +1,4 @@ -import prisma from '@prisma/client' +import type prisma from '@prisma/client' import { getPrismaClient } from './utils/prismaClient' import { type EntityMetadata, @@ -40,8 +40,8 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { { where: { blockNumber: { - gte: fromBlock, - lte: toBlock + gte: firstBlock, + lte: lastBlock } } } @@ -54,7 +54,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const existingRecord = operatorList.get(operatorAddress) const blockNumber = BigInt(log.blockNumber) - const timestamp = new Date(Number(log.blockTime) * 1000) + const timestamp = log.blockTime try { if (log.metadataURI && isValidMetadataUrl(log.metadataURI)) { @@ -103,7 +103,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { } console.log( - `Operators registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` + `Operators registered between blocks ${firstBlock} ${lastBlock}: ${logs.length}` ) // Prepare db transaction object diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index 6fe4b9d9..7762bdc9 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -30,8 +30,8 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { const logs = await prismaClient.eventLogs_PodDeployed.findMany({ where: { blockNumber: { - gte: fromBlock, - lte: toBlock + gte: firstBlock, + lte: lastBlock } } }) @@ -43,7 +43,7 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { const podOwner = String(log.podOwner).toLowerCase() const blockNumber = BigInt(log.blockNumber) - const timestamp = new Date(Number(log.blockTime) * 1000) + const timestamp = log.blockTime podList.push({ address: podAddress, diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index b7a891c9..c9c30938 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -43,8 +43,8 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: fromBlock, - lte: toBlock + gte: firstBlock, + lte: lastBlock } } }) @@ -56,8 +56,8 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: fromBlock, - lte: toBlock + gte: firstBlock, + lte: lastBlock } } }) @@ -70,8 +70,8 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: fromBlock, - lte: toBlock + gte: firstBlock, + lte: lastBlock } } }) @@ -84,8 +84,8 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: fromBlock, - lte: toBlock + gte: firstBlock, + lte: lastBlock } } }) @@ -116,7 +116,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { const stakerAddress = String(log.staker).toLowerCase() const blockNumber = BigInt(log.blockNumber) - const timestamp = new Date(Number(log.blockTime) * 1000) + const timestamp = log.blockTime // Load existing staker shares data if (!stakers.has(stakerAddress)) { @@ -162,7 +162,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { log.eventName === 'OperatorSharesDecreased' ) { const strategyAddress = String(log.strategy).toLowerCase() - const shares = BigInt(log.shares) + const shares = log.shares if (!shares) continue let foundSharesIndex = stakers @@ -185,10 +185,12 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { if (log.eventName === 'OperatorSharesIncreased') { stakers.get(stakerAddress).shares[foundSharesIndex].shares = - stakers.get(stakerAddress).shares[foundSharesIndex].shares + shares + stakers.get(stakerAddress).shares[foundSharesIndex].shares + + BigInt(shares) } else if (log.eventName === 'OperatorSharesDecreased') { stakers.get(stakerAddress).shares[foundSharesIndex].shares = - stakers.get(stakerAddress).shares[foundSharesIndex].shares - shares + stakers.get(stakerAddress).shares[foundSharesIndex].shares - + BigInt(shares) } } } From 28e31d3372a57678bc1c14fbf4a9cf5a48b71c43 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Wed, 5 Jun 2024 17:44:50 +0530 Subject: [PATCH 26/62] increased efficiency of block seeder and event logs seeder --- packages/seeder/src/events/seedBlockData.ts | 44 +- packages/seeder/src/events/seedEventLogs.ts | 75 +- packages/seeder/src/index.ts | 5 +- packages/seeder/src/seedAvsOperators.ts | 2 +- packages/seeder/src/seedOperatorShares.ts | 2 +- packages/seeder/src/seedPods.ts | 2 +- packages/seeder/src/seedStakers.ts | 10 +- packages/seeder/src/utils/events.ts | 889 +++++++------------- 8 files changed, 345 insertions(+), 684 deletions(-) diff --git a/packages/seeder/src/events/seedBlockData.ts b/packages/seeder/src/events/seedBlockData.ts index c496c4e4..99d34ade 100644 --- a/packages/seeder/src/events/seedBlockData.ts +++ b/packages/seeder/src/events/seedBlockData.ts @@ -2,7 +2,6 @@ import type prisma from '@prisma/client' import { getPrismaClient } from '../utils/prismaClient' import { getViemClient } from '../utils/viemClient' import { - baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, loopThroughBlocks, @@ -58,39 +57,22 @@ export async function seedBlockData(toBlock?: bigint, fromBlock?: bigint) { // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] - if (firstBlock === baseBlock) { - dbTransactions.push(prismaClient.evm_BlockData.deleteMany()) + const newBlockData: prisma.Evm_BlockData[] = [] - const newBlockData: prisma.Evm_BlockData[] = [] - - for (const [number, timestamp] of blockList) { - newBlockData.push({ - number, - timestamp - }) - } - - dbTransactions.push( - prismaClient.evm_BlockData.createMany({ - data: newBlockData, - skipDuplicates: true - }) - ) - } else { - for (const [number, timestamp] of blockList) { - dbTransactions.push( - prismaClient.evm_BlockData.upsert({ - where: { number }, - update: {}, - create: { - number, - timestamp - } - }) - ) - } + for (const [number, timestamp] of blockList) { + newBlockData.push({ + number, + timestamp + }) } + dbTransactions.push( + prismaClient.evm_BlockData.createMany({ + data: newBlockData, + skipDuplicates: true + }) + ) + await bulkUpdateDbTransactions(dbTransactions) // Storing last sycned block diff --git a/packages/seeder/src/events/seedEventLogs.ts b/packages/seeder/src/events/seedEventLogs.ts index 1ada7483..f00959fe 100644 --- a/packages/seeder/src/events/seedEventLogs.ts +++ b/packages/seeder/src/events/seedEventLogs.ts @@ -2,7 +2,6 @@ import { parseAbiItem } from 'viem' import { getEigenContracts } from '../data/address' import { getViemClient } from '../utils/viemClient' import { - baseBlock, fetchLastSyncBlock, loopThroughBlocks, saveLastSyncBlock @@ -127,30 +126,33 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { switch (log.eventName) { case 'AVSMetadataURIUpdated': { const eventData: AVSMetadataURIUpdatedLog = { - avs: String(log.args.avs).toLowerCase(), - metadataURI: String(log.args.metadataURI).toLowerCase() + avs: log.args.avs, + metadataURI: log.args.metadataURI } avsMetadataURIUpdatedList.set(transactionData, eventData) + break } case 'OperatorAVSRegistrationStatusUpdated': { const eventData: OperatorAVSRegistrationStatusUpdatedLog = { - operator: String(log.args.operator).toLowerCase(), - avs: String(log.args.avs).toLowerCase(), + operator: log.args.operator, + avs: log.args.avs, status: log.args.status || 0 } operatorAVSRegistrationStatusUpdatedList.set( transactionData, eventData ) + break } case 'OperatorMetadataURIUpdated': { const eventData: OperatorMetadataURIUpdatedLog = { - operator: String(log.args.operator).toLowerCase(), - metadataURI: String(log.args.metadataURI).toLowerCase() + operator: log.args.operator, + metadataURI: log.args.metadataURI } operatorMetadataURIUpdatedList.set(transactionData, eventData) + break } case 'OperatorSharesIncreased': { @@ -158,12 +160,13 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { if (!shares) continue const eventData: OperatorSharesIncreasedLog = { - operator: String(log.args.operator).toLowerCase(), - staker: String(log.args.staker).toLowerCase(), - strategy: String(log.args.strategy).toLowerCase(), + operator: log.args.operator, + staker: log.args.staker, + strategy: log.args.strategy, shares: shares.toString() } operatorSharesIncreasedList.set(transactionData, eventData) + break } case 'OperatorSharesDecreased': { @@ -171,34 +174,40 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { if (!shares) continue const eventData: OperatorSharesDecreasedLog = { - operator: String(log.args.operator).toLowerCase(), - staker: String(log.args.staker).toLowerCase(), - strategy: String(log.args.strategy).toLowerCase(), + operator: log.args.operator, + staker: log.args.staker, + strategy: log.args.strategy, shares: shares.toString() } operatorSharesDecreasedList.set(transactionData, eventData) + break } case 'PodDeployed': { const eventData: PodDeployedLog = { - eigenPod: String(log.args.eigenPod).toLowerCase(), - podOwner: String(log.args.podOwner).toLowerCase() + eigenPod: log.args.eigenPod, + podOwner: log.args.podOwner } podDeployedList.set(transactionData, eventData) + break } case 'StakerDelegated': { + const staker = log.args.staker + if (!staker) continue + const eventData: StakerDelegatedLog = { - staker: String(log.args.staker).toLowerCase(), - operator: String(log.args.operator).toLowerCase() + staker: staker, + operator: log.args.operator } stakerDelegatedList.set(transactionData, eventData) + break } case 'StakerUndelegated': { const eventData: StakerUndelegatedLog = { - staker: String(log.args.staker).toLowerCase(), - operator: String(log.args.operator).toLowerCase() + staker: log.args.staker, + operator: log.args.operator } stakerUndelegatedList.set(transactionData, eventData) } @@ -212,41 +221,31 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { // Update all EventLog tables with the respective event log data // biome-ignore lint/suspicious/noExplicitAny: - let dbTransactions: any[] = [] - const flag = firstBlock === baseBlock + const dbTransactions: any[] = [] await updateTableAVSMetadataURIUpdated( dbTransactions, - avsMetadataURIUpdatedList, - flag + avsMetadataURIUpdatedList ) await updateTableOperatorAVSRegistrationStatusUpdated( dbTransactions, - operatorAVSRegistrationStatusUpdatedList, - flag + operatorAVSRegistrationStatusUpdatedList ) await updateTableOperatorMetadataURIUpdated( dbTransactions, - operatorMetadataURIUpdatedList, - flag + operatorMetadataURIUpdatedList ) await updateTableOperatorSharesIncreased( dbTransactions, - operatorSharesIncreasedList, - flag + operatorSharesIncreasedList ) await updateTableOperatorSharesDecreased( dbTransactions, - operatorSharesDecreasedList, - flag - ) - await updateTablePodDeployed(dbTransactions, podDeployedList, flag) - await updateTableStakerDelegated(dbTransactions, stakerDelegatedList, flag) - await updateTableStakerUndelegated( - dbTransactions, - stakerUndelegatedList, - flag + operatorSharesDecreasedList ) + await updateTablePodDeployed(dbTransactions, podDeployedList) + await updateTableStakerDelegated(dbTransactions, stakerDelegatedList) + await updateTableStakerUndelegated(dbTransactions, stakerUndelegatedList) // Store last synced block await saveLastSyncBlock(blockSyncKey, lastBlock) diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 1242f348..1aa454e3 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -6,6 +6,7 @@ import { seedOperators } from './seedOperators' import { seedPods } from './seedPods' import { seedStakers } from './seedStakers' import { getViemClient } from './utils/viemClient' +import { baseBlock } from './utils/seeder' import { seedBlockData } from './events/seedBlockData' import { seedEventLogs } from './events/seedEventLogs' import { seedOperatorShares } from './seedOperatorShares' @@ -44,7 +45,7 @@ async function seedEigenDataLoop() { while (true) { try { const targetBlock = await fetchLastSyncBlock(blockSyncKey) - if (targetBlock <= 1159609n) { + if (targetBlock === baseBlock) { delay(60) continue } @@ -73,7 +74,7 @@ async function seedEigenPodValidators() { while (true) { try { const targetBlock = await fetchLastSyncBlock(blockSyncKey) - if (!targetBlock) { + if (targetBlock === baseBlock) { delay(60) continue } diff --git a/packages/seeder/src/seedAvsOperators.ts b/packages/seeder/src/seedAvsOperators.ts index d2ae9f9b..12d5ec19 100644 --- a/packages/seeder/src/seedAvsOperators.ts +++ b/packages/seeder/src/seedAvsOperators.ts @@ -50,7 +50,7 @@ export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { } console.log( - `Avs operators updated between blocks ${fromBlock} ${toBlock}: ${logs.length}` + `Avs operators updated between blocks ${firstBlock} ${lastBlock}: ${logs.length}` ) // Prepare db transaction object diff --git a/packages/seeder/src/seedOperatorShares.ts b/packages/seeder/src/seedOperatorShares.ts index 8721979f..7e368864 100644 --- a/packages/seeder/src/seedOperatorShares.ts +++ b/packages/seeder/src/seedOperatorShares.ts @@ -127,7 +127,7 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { } console.log( - `Operator shares updated between blocks ${fromBlock} ${toBlock}: ${logs.length}` + `Operator shares updated between blocks ${firstBlock} ${lastBlock}: ${logs.length}` ) // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index 7762bdc9..111f2fd8 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -57,7 +57,7 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { } console.log( - `Pods deployed between blocks ${fromBlock} ${toBlock}: ${logs.length}` + `Pods deployed between blocks ${firstBlock} ${lastBlock}: ${logs.length}` ) // Prepare db transaction object diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index c9c30938..8374fc6f 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -162,7 +162,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { log.eventName === 'OperatorSharesDecreased' ) { const strategyAddress = String(log.strategy).toLowerCase() - const shares = log.shares + const shares = BigInt(log.shares) if (!shares) continue let foundSharesIndex = stakers @@ -185,18 +185,16 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { if (log.eventName === 'OperatorSharesIncreased') { stakers.get(stakerAddress).shares[foundSharesIndex].shares = - stakers.get(stakerAddress).shares[foundSharesIndex].shares + - BigInt(shares) + stakers.get(stakerAddress).shares[foundSharesIndex].shares + shares } else if (log.eventName === 'OperatorSharesDecreased') { stakers.get(stakerAddress).shares[foundSharesIndex].shares = - stakers.get(stakerAddress).shares[foundSharesIndex].shares - - BigInt(shares) + stakers.get(stakerAddress).shares[foundSharesIndex].shares - shares } } } console.log( - `Stakers deployed between blocks ${fromBlock} ${toBlock}: ${logs.length}` + `Stakers deployed between blocks ${firstBlock} ${lastBlock}: ${logs.length}` ) // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/utils/events.ts b/packages/seeder/src/utils/events.ts index 0ef08ebf..488552a1 100644 --- a/packages/seeder/src/utils/events.ts +++ b/packages/seeder/src/utils/events.ts @@ -1,4 +1,4 @@ -import prisma from '@prisma/client' +import type prisma from '@prisma/client' import { getPrismaClient } from '../utils/prismaClient' import { bulkUpdateDbTransactions } from '../utils/seeder' @@ -14,716 +14,397 @@ export interface TransactionLog { } export interface AVSMetadataURIUpdatedLog { - avs: string - metadataURI: string + avs: `0x${string}` | undefined + metadataURI: string | undefined } export interface OperatorAVSRegistrationStatusUpdatedLog { - operator: string - avs: string + operator: `0x${string}` | undefined + avs: `0x${string}` | undefined status: number } export interface OperatorMetadataURIUpdatedLog { - operator: string - metadataURI: string + operator: `0x${string}` | undefined + metadataURI: string | undefined } export interface OperatorSharesIncreasedLog { - operator: string - staker: string - strategy: string + operator: `0x${string}` | undefined + staker: `0x${string}` | undefined + strategy: `0x${string}` | undefined shares: string } export interface OperatorSharesDecreasedLog { - operator: string - staker: string - strategy: string + operator: `0x${string}` | undefined + staker: `0x${string}` | undefined + strategy: `0x${string}` | undefined shares: string } export interface PodDeployedLog { - eigenPod: string - podOwner: string + eigenPod: `0x${string}` | undefined + podOwner: `0x${string}` | undefined } export interface StakerDelegatedLog { - staker: string - operator: string + staker: `0x${string}` | undefined + operator: `0x${string}` | undefined } export interface StakerUndelegatedLog { - staker: string - operator: string + staker: `0x${string}` | undefined + operator: `0x${string}` | undefined } export async function updateTableAVSMetadataURIUpdated( + // biome-ignore lint/suspicious/noExplicitAny: dbTransactions: any[], - avsMetadataURIUpdatedList: Map, - deleteAll: boolean = false + avsMetadataURIUpdatedList: Map ) { try { - if (deleteAll) { - dbTransactions.push( - prismaClient.eventLogs_AVSMetadataURIUpdated.deleteMany() - ) - - const newAvsMetadataURIUpdated: prisma.EventLogs_AVSMetadataURIUpdated[] = - [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { avs, metadataURI } - ] of avsMetadataURIUpdatedList) { - newAvsMetadataURIUpdated.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - avs, - metadataURI - }) - } - - dbTransactions.push( - prismaClient.eventLogs_AVSMetadataURIUpdated.createMany({ - data: newAvsMetadataURIUpdated, - skipDuplicates: true - }) - ) - } else { - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { avs, metadataURI } - ] of avsMetadataURIUpdatedList) { - dbTransactions.push( - prismaClient.eventLogs_AVSMetadataURIUpdated.upsert({ - where: { - transactionHash_transactionIndex: { - transactionHash: transactionHash, - transactionIndex: transactionIndex - } - }, - update: {}, - create: { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - avs, - metadataURI - } - }) - ) - } + const newAvsMetadataURIUpdated: prisma.EventLogs_AVSMetadataURIUpdated[] = + [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { avs, metadataURI } + ] of avsMetadataURIUpdatedList) { + newAvsMetadataURIUpdated.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + avs, + metadataURI + }) } + + dbTransactions.push( + prismaClient.eventLogs_AVSMetadataURIUpdated.createMany({ + data: newAvsMetadataURIUpdated, + skipDuplicates: true + }) + ) } catch {} await bulkUpdateDbTransactions(dbTransactions) } export async function updateTableOperatorAVSRegistrationStatusUpdated( + // biome-ignore lint/suspicious/noExplicitAny: dbTransactions: any[], operatorAVSRegistrationStatusUpdatedList: Map< TransactionLog, OperatorAVSRegistrationStatusUpdatedLog - >, - deleteAll: boolean = false + > ) { try { - if (deleteAll) { - dbTransactions.push( - prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.deleteMany() - ) - - const newOperatorAVSRegistrationStatusUpdated: prisma.EventLogs_OperatorAVSRegistrationStatusUpdated[] = - [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, avs, status } - ] of operatorAVSRegistrationStatusUpdatedList) { - newOperatorAVSRegistrationStatusUpdated.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - avs, - status - }) - } - - dbTransactions.push( - prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.createMany({ - data: newOperatorAVSRegistrationStatusUpdated, - skipDuplicates: true - }) - ) - } else { - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, avs, status } - ] of operatorAVSRegistrationStatusUpdatedList) { - dbTransactions.push( - prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.upsert({ - where: { - transactionHash_transactionIndex: { - transactionHash: transactionHash, - transactionIndex: transactionIndex - } - }, - update: {}, - create: { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - avs, - status - } - }) - ) - } + const newOperatorAVSRegistrationStatusUpdated: prisma.EventLogs_OperatorAVSRegistrationStatusUpdated[] = + [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, avs, status } + ] of operatorAVSRegistrationStatusUpdatedList) { + newOperatorAVSRegistrationStatusUpdated.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + avs, + status + }) } + + dbTransactions.push( + prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.createMany({ + data: newOperatorAVSRegistrationStatusUpdated, + skipDuplicates: true + }) + ) } catch {} await bulkUpdateDbTransactions(dbTransactions) } export async function updateTableOperatorMetadataURIUpdated( + // biome-ignore lint/suspicious/noExplicitAny: dbTransactions: any[], operatorMetadataURIUpdatedList: Map< TransactionLog, OperatorMetadataURIUpdatedLog - >, - deleteAll: boolean = false + > ) { try { - if (deleteAll) { - dbTransactions.push( - prismaClient.eventLogs_OperatorMetadataURIUpdated.deleteMany() - ) - - const newOperatorMetadataURIUpdated: prisma.EventLogs_OperatorMetadataURIUpdated[] = - [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, metadataURI } - ] of operatorMetadataURIUpdatedList) { - newOperatorMetadataURIUpdated.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - metadataURI - }) - } - - dbTransactions.push( - prismaClient.eventLogs_OperatorMetadataURIUpdated.createMany({ - data: newOperatorMetadataURIUpdated, - skipDuplicates: true - }) - ) - } else { - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, metadataURI } - ] of operatorMetadataURIUpdatedList) { - dbTransactions.push( - prismaClient.eventLogs_OperatorMetadataURIUpdated.upsert({ - where: { - transactionHash_transactionIndex: { - transactionHash: transactionHash, - transactionIndex: transactionIndex - } - }, - update: {}, - create: { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - metadataURI - } - }) - ) - } + const newOperatorMetadataURIUpdated: prisma.EventLogs_OperatorMetadataURIUpdated[] = + [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, metadataURI } + ] of operatorMetadataURIUpdatedList) { + newOperatorMetadataURIUpdated.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + metadataURI + }) } + + dbTransactions.push( + prismaClient.eventLogs_OperatorMetadataURIUpdated.createMany({ + data: newOperatorMetadataURIUpdated, + skipDuplicates: true + }) + ) } catch {} await bulkUpdateDbTransactions(dbTransactions) } export async function updateTableOperatorSharesIncreased( + // biome-ignore lint/suspicious/noExplicitAny: dbTransactions: any[], - operatorSharesIncreasedList: Map, - deleteAll: boolean = false + operatorSharesIncreasedList: Map ) { try { - if (deleteAll) { - dbTransactions.push( - prismaClient.eventLogs_OperatorSharesIncreased.deleteMany() - ) - - const newOperatorSharesIncreased: prisma.EventLogs_OperatorSharesIncreased[] = - [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, staker, strategy, shares } - ] of operatorSharesIncreasedList) { - newOperatorSharesIncreased.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - staker, - strategy, - shares - }) - } - - dbTransactions.push( - prismaClient.eventLogs_OperatorSharesIncreased.createMany({ - data: newOperatorSharesIncreased, - skipDuplicates: true - }) - ) - } else { - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, staker, strategy, shares } - ] of operatorSharesIncreasedList) { - dbTransactions.push( - prismaClient.eventLogs_OperatorSharesIncreased.upsert({ - where: { - transactionHash_transactionIndex: { - transactionHash: transactionHash, - transactionIndex: transactionIndex - } - }, - update: {}, - create: { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - staker, - strategy, - shares - } - }) - ) - } + const newOperatorSharesIncreased: prisma.EventLogs_OperatorSharesIncreased[] = + [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, staker, strategy, shares } + ] of operatorSharesIncreasedList) { + newOperatorSharesIncreased.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + staker, + strategy, + shares + }) } + + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesIncreased.createMany({ + data: newOperatorSharesIncreased, + skipDuplicates: true + }) + ) } catch {} await bulkUpdateDbTransactions(dbTransactions) } export async function updateTableOperatorSharesDecreased( + // biome-ignore lint/suspicious/noExplicitAny: dbTransactions: any[], - operatorSharesDecreasedList: Map, - deleteAll: boolean = false + operatorSharesDecreasedList: Map ) { try { - if (deleteAll) { - dbTransactions.push( - prismaClient.eventLogs_OperatorSharesDecreased.deleteMany() - ) - - const newOperatorSharesDecreased: prisma.EventLogs_OperatorSharesDecreased[] = - [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, staker, strategy, shares } - ] of operatorSharesDecreasedList) { - newOperatorSharesDecreased.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - staker, - strategy, - shares - }) - } - - dbTransactions.push( - prismaClient.eventLogs_OperatorSharesDecreased.createMany({ - data: newOperatorSharesDecreased, - skipDuplicates: true - }) - ) - } else { - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, staker, strategy, shares } - ] of operatorSharesDecreasedList) { - dbTransactions.push( - prismaClient.eventLogs_OperatorSharesDecreased.upsert({ - where: { - transactionHash_transactionIndex: { - transactionHash: transactionHash, - transactionIndex: transactionIndex - } - }, - update: {}, - create: { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - staker, - strategy, - shares - } - }) - ) - } + const newOperatorSharesDecreased: prisma.EventLogs_OperatorSharesDecreased[] = + [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { operator, staker, strategy, shares } + ] of operatorSharesDecreasedList) { + newOperatorSharesDecreased.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + operator, + staker, + strategy, + shares + }) } + + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesDecreased.createMany({ + data: newOperatorSharesDecreased, + skipDuplicates: true + }) + ) } catch {} await bulkUpdateDbTransactions(dbTransactions) } export async function updateTablePodDeployed( + // biome-ignore lint/suspicious/noExplicitAny: dbTransactions: any[], - podDeployedList: Map, - deleteAll: boolean = false + podDeployedList: Map ) { try { - if (deleteAll) { - dbTransactions.push(prismaClient.eventLogs_PodDeployed.deleteMany()) - - const newPodDeployed: prisma.EventLogs_PodDeployed[] = [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { eigenPod, podOwner } - ] of podDeployedList) { - newPodDeployed.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - eigenPod, - podOwner - }) - } - - dbTransactions.push( - prismaClient.eventLogs_PodDeployed.createMany({ - data: newPodDeployed, - skipDuplicates: true - }) - ) - } else { - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { eigenPod, podOwner } - ] of podDeployedList) { - dbTransactions.push( - prismaClient.eventLogs_PodDeployed.upsert({ - where: { - transactionHash_transactionIndex: { - transactionHash: transactionHash, - transactionIndex: transactionIndex - } - }, - update: {}, - create: { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - eigenPod, - podOwner - } - }) - ) - } + const newPodDeployed: prisma.EventLogs_PodDeployed[] = [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { eigenPod, podOwner } + ] of podDeployedList) { + newPodDeployed.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + eigenPod, + podOwner + }) } + + dbTransactions.push( + prismaClient.eventLogs_PodDeployed.createMany({ + data: newPodDeployed, + skipDuplicates: true + }) + ) } catch {} await bulkUpdateDbTransactions(dbTransactions) } export async function updateTableStakerDelegated( + // biome-ignore lint/suspicious/noExplicitAny: dbTransactions: any[], - stakerDelegatedList: Map, - deleteAll: boolean = false + stakerDelegatedList: Map ) { try { - if (deleteAll) { - dbTransactions.push(prismaClient.eventLogs_StakerDelegated.deleteMany()) - - const newStakerDelegated: prisma.EventLogs_StakerDelegated[] = [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { staker, operator } - ] of stakerDelegatedList) { - newStakerDelegated.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - staker, - operator - }) - } - - dbTransactions.push( - prismaClient.eventLogs_StakerDelegated.createMany({ - data: newStakerDelegated, - skipDuplicates: true - }) - ) - } else { - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { staker, operator } - ] of stakerDelegatedList) { - dbTransactions.push( - prismaClient.eventLogs_StakerDelegated.upsert({ - where: { - transactionHash_transactionIndex: { - transactionHash: transactionHash, - transactionIndex: transactionIndex - } - }, - update: {}, - create: { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - staker, - operator - } - }) - ) - } + const newStakerDelegated: prisma.EventLogs_StakerDelegated[] = [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { staker, operator } + ] of stakerDelegatedList) { + newStakerDelegated.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + staker, + operator + }) } + + dbTransactions.push( + prismaClient.eventLogs_StakerDelegated.createMany({ + data: newStakerDelegated, + skipDuplicates: true + }) + ) } catch {} await bulkUpdateDbTransactions(dbTransactions) } export async function updateTableStakerUndelegated( + // biome-ignore lint/suspicious/noExplicitAny: dbTransactions: any[], - stakerUndelegatedList: Map, - deleteAll: boolean = false + stakerUndelegatedList: Map ) { try { - if (deleteAll) { - dbTransactions.push(prismaClient.eventLogs_StakerUndelegated.deleteMany()) - - const newStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { staker, operator } - ] of stakerUndelegatedList) { - newStakerUndelegated.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - staker, - operator - }) - } - - dbTransactions.push( - prismaClient.eventLogs_StakerUndelegated.createMany({ - data: newStakerUndelegated, - skipDuplicates: true - }) - ) - } else { - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { staker, operator } - ] of stakerUndelegatedList) { - dbTransactions.push( - prismaClient.eventLogs_StakerUndelegated.upsert({ - where: { - transactionHash_transactionIndex: { - transactionHash: transactionHash, - transactionIndex: transactionIndex - } - }, - update: {}, - create: { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - staker, - operator - } - }) - ) - } + const newStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] + + for (const [ + { + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime + }, + { staker, operator } + ] of stakerUndelegatedList) { + newStakerUndelegated.push({ + address, + transactionHash, + transactionIndex, + blockNumber, + blockHash, + blockTime, + staker, + operator + }) } + + dbTransactions.push( + prismaClient.eventLogs_StakerUndelegated.createMany({ + data: newStakerUndelegated, + skipDuplicates: true + }) + ) } catch {} await bulkUpdateDbTransactions(dbTransactions) From bf878c1845f8930d35ee607cb2f227539ef379c1 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Wed, 5 Jun 2024 19:20:22 +0530 Subject: [PATCH 27/62] bug fixes --- packages/seeder/src/events/seedEventLogs.ts | 4 ++-- packages/seeder/src/index.ts | 13 +++++-------- packages/seeder/src/seedAvs.ts | 5 +++-- packages/seeder/src/seedAvsOperators.ts | 5 ++--- packages/seeder/src/seedOperatorShares.ts | 5 ++--- packages/seeder/src/seedOperators.ts | 5 ++--- packages/seeder/src/seedPods.ts | 7 +++---- packages/seeder/src/seedStakers.ts | 14 +++++--------- packages/seeder/src/utils/events.ts | 14 +++++++++++++- 9 files changed, 37 insertions(+), 35 deletions(-) diff --git a/packages/seeder/src/events/seedEventLogs.ts b/packages/seeder/src/events/seedEventLogs.ts index f00959fe..438270d3 100644 --- a/packages/seeder/src/events/seedEventLogs.ts +++ b/packages/seeder/src/events/seedEventLogs.ts @@ -16,7 +16,7 @@ import { type PodDeployedLog, type StakerDelegatedLog, type StakerUndelegatedLog, - getBlockDataFromDB, + getBlockDataFromDb, updateTableAVSMetadataURIUpdated, updateTableOperatorAVSRegistrationStatusUpdated, updateTableOperatorMetadataURIUpdated, @@ -69,7 +69,7 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { ? fromBlock : await fetchLastSyncBlock(blockSyncKey) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - const blockData = await getBlockDataFromDB(firstBlock, lastBlock) + const blockData = await getBlockDataFromDb(firstBlock, lastBlock) // Loop through evm logs for all 8 events from 3 contracts await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 1aa454e3..73cd17fe 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -6,19 +6,16 @@ import { seedOperators } from './seedOperators' import { seedPods } from './seedPods' import { seedStakers } from './seedStakers' import { getViemClient } from './utils/viemClient' -import { baseBlock } from './utils/seeder' import { seedBlockData } from './events/seedBlockData' import { seedEventLogs } from './events/seedEventLogs' import { seedOperatorShares } from './seedOperatorShares' import { seedValidators } from './seedValidators' import { seedQueuedWithdrawals } from './seedWithdrawalsQueued' import { seedCompletedWithdrawals } from './seedWithdrawalsCompleted' -import { fetchLastSyncBlock } from './utils/seeder' +import { fetchLastLogBlock } from './utils/events' console.log('Initializing seeder ...') -const blockSyncKey = 'lastSyncedBlock_logs' - function delay(seconds: number) { return new Promise((resolve) => setTimeout(resolve, seconds * 1000)) } @@ -44,8 +41,8 @@ async function seedEventLogsLoop() { async function seedEigenDataLoop() { while (true) { try { - const targetBlock = await fetchLastSyncBlock(blockSyncKey) - if (targetBlock === baseBlock) { + const targetBlock = await fetchLastLogBlock() + if (!targetBlock) { delay(60) continue } @@ -73,8 +70,8 @@ async function seedEigenPodValidators() { while (true) { try { - const targetBlock = await fetchLastSyncBlock(blockSyncKey) - if (targetBlock === baseBlock) { + const targetBlock = await fetchLastLogBlock() + if (!targetBlock) { delay(60) continue } diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 346dacc4..7063eee6 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -1,8 +1,9 @@ -import prisma from '@prisma/client' +import type prisma from '@prisma/client' import { isValidMetadataUrl, validateMetadata } from './utils/metadata' import { type EntityMetadata, defaultMetadata } from './utils/metadata' import { getViemClient } from './utils/viemClient' import { getPrismaClient } from './utils/prismaClient' +import { fetchLastLogBlock } from './utils/events' import { baseBlock, bulkUpdateDbTransactions, @@ -36,7 +37,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() const logs = await prismaClient.eventLogs_AVSMetadataURIUpdated.findMany({ where: { diff --git a/packages/seeder/src/seedAvsOperators.ts b/packages/seeder/src/seedAvsOperators.ts index 12d5ec19..7978cf20 100644 --- a/packages/seeder/src/seedAvsOperators.ts +++ b/packages/seeder/src/seedAvsOperators.ts @@ -1,4 +1,4 @@ -import { getViemClient } from './utils/viemClient' +import { fetchLastLogBlock } from './utils/events' import { getPrismaClient } from './utils/prismaClient' import { baseBlock, @@ -12,14 +12,13 @@ const blockSyncKey = 'lastSyncedBlock_avsOperators' export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { console.log('Seeding AVS Operators ...') - const viemClient = getViemClient() const prismaClient = getPrismaClient() const avsOperatorsList: Map> = new Map() const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() // Load initial operator staker state const avs = await prismaClient.avs.findMany({ diff --git a/packages/seeder/src/seedOperatorShares.ts b/packages/seeder/src/seedOperatorShares.ts index 7e368864..422f52e6 100644 --- a/packages/seeder/src/seedOperatorShares.ts +++ b/packages/seeder/src/seedOperatorShares.ts @@ -1,5 +1,5 @@ -import { getViemClient } from './utils/viemClient' import { getPrismaClient } from './utils/prismaClient' +import { fetchLastLogBlock } from './utils/events' import { baseBlock, bulkUpdateDbTransactions, @@ -13,7 +13,6 @@ const blockSyncKey = 'lastSyncedBlock_operatorShares' export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { console.log('Seeding operator shares ...') - const viemClient = getViemClient() const prismaClient = getPrismaClient() const operatorShares: IMap< string, @@ -23,7 +22,7 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() if (firstBlock === baseBlock) { await prismaClient.operatorStrategyShares.deleteMany() diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index bd500760..a9c9d6ca 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -6,7 +6,7 @@ import { isValidMetadataUrl, validateMetadata } from './utils/metadata' -import { getViemClient } from './utils/viemClient' +import { fetchLastLogBlock } from './utils/events' import { baseBlock, bulkUpdateDbTransactions, @@ -27,14 +27,13 @@ interface OperatorEntryRecord { export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { console.log('Seeding Operators ...') - const viemClient = getViemClient() const prismaClient = getPrismaClient() const operatorList: Map = new Map() const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() const logs = await prismaClient.eventLogs_OperatorMetadataURIUpdated.findMany( { diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index 111f2fd8..e435bafd 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -1,5 +1,5 @@ -import prisma from '@prisma/client' -import { getViemClient } from './utils/viemClient' +import type prisma from '@prisma/client' +import { fetchLastLogBlock } from './utils/events' import { getPrismaClient } from './utils/prismaClient' import { baseBlock, @@ -18,14 +18,13 @@ const blockSyncKey = 'lastSyncedBlock_pods' export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { console.log('Seeding Pods ...') - const viemClient = getViemClient() const prismaClient = getPrismaClient() const podList: prisma.Pod[] = [] const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() const logs = await prismaClient.eventLogs_PodDeployed.findMany({ where: { diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index 8374fc6f..6a4daca1 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -1,14 +1,11 @@ -import prisma from '@prisma/client' -import { parseAbiItem } from 'viem' -import { getEigenContracts } from './data/address' -import { getViemClient } from './utils/viemClient' +import type prisma from '@prisma/client' +import { fetchLastLogBlock } from './utils/events' import { getPrismaClient } from './utils/prismaClient' import { type IMap, baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, - loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -26,14 +23,13 @@ interface StakerEntryRecord { export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { console.log('Seeding stakers ...') - const viemClient = getViemClient() const prismaClient = getPrismaClient() const stakers: IMap = new Map() const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() if (firstBlock === baseBlock) { await prismaClient.stakerStrategyShares.deleteMany() @@ -62,7 +58,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } }) .then((logs) => - logs.map((log) => ({ ...log, eventName: 'OperatorSharesIncreased' })) + logs.map((log) => ({ ...log, eventName: 'StakerUndelegated' })) ) const logsOperatorSharesIncreased = @@ -76,7 +72,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } }) .then((logs) => - logs.map((log) => ({ ...log, eventName: 'OperatorSharesDecreased' })) + logs.map((log) => ({ ...log, eventName: 'OperatorSharesIncreased' })) ) const logsOperatorSharesDecreased = diff --git a/packages/seeder/src/utils/events.ts b/packages/seeder/src/utils/events.ts index 488552a1..44183a5d 100644 --- a/packages/seeder/src/utils/events.ts +++ b/packages/seeder/src/utils/events.ts @@ -410,7 +410,7 @@ export async function updateTableStakerUndelegated( await bulkUpdateDbTransactions(dbTransactions) } -export async function getBlockDataFromDB(fromBlock: bigint, toBlock: bigint) { +export async function getBlockDataFromDb(fromBlock: bigint, toBlock: bigint) { const blockData = await prismaClient.evm_BlockData.findMany({ where: { number: { @@ -429,3 +429,15 @@ export async function getBlockDataFromDB(fromBlock: bigint, toBlock: bigint) { return new Map(blockData.map((block) => [block.number, block.timestamp])) } + +export async function fetchLastLogBlock(): Promise { + const prismaClient = getPrismaClient() + + const lastSyncedBlockData = await prismaClient.settings.findUnique({ + where: { key: 'lastSyncedBlock_logs' } + }) + + return lastSyncedBlockData?.value + ? BigInt(lastSyncedBlockData.value as number) + : 0n +} From 3c6c597fd2d4ae85f7a29c01d4f234fca61f8518 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Thu, 6 Jun 2024 03:20:29 +0530 Subject: [PATCH 28/62] Optimizations to the block data and logs seeder scripts --- packages/seeder/src/events/seedBlockData.ts | 86 ++-- packages/seeder/src/events/seedEventLogs.ts | 293 +++++++------- packages/seeder/src/index.ts | 38 +- packages/seeder/src/utils/events.ts | 423 +------------------- packages/seeder/src/utils/seeder.ts | 28 +- 5 files changed, 215 insertions(+), 653 deletions(-) diff --git a/packages/seeder/src/events/seedBlockData.ts b/packages/seeder/src/events/seedBlockData.ts index 99d34ade..a19d6a01 100644 --- a/packages/seeder/src/events/seedBlockData.ts +++ b/packages/seeder/src/events/seedBlockData.ts @@ -1,82 +1,58 @@ -import type prisma from '@prisma/client' +import prisma from '@prisma/client' import { getPrismaClient } from '../utils/prismaClient' import { getViemClient } from '../utils/viemClient' -import { - bulkUpdateDbTransactions, - fetchLastSyncBlock, - loopThroughBlocks, - saveLastSyncBlock -} from '../utils/seeder' - -const blockSyncKey = 'lastSyncedBlock_blockdata' +import { baseBlock, loopThroughBlocks } from '../utils/seeder' export async function seedBlockData(toBlock?: bigint, fromBlock?: bigint) { console.log('Seeding Block Data ...') const viemClient = getViemClient() const prismaClient = getPrismaClient() - const blockList: Map = new Map() + + const lastKnownBlock = await prismaClient.evm_BlockData.findFirst({ + orderBy: { number: 'desc' } + }) const firstBlock = fromBlock ? fromBlock - : await fetchLastSyncBlock(blockSyncKey) + : lastKnownBlock + ? lastKnownBlock.number + : baseBlock + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() // Retrieve blocks in batches and extract timestamps - await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - let currentBlock = fromBlock - - while (currentBlock <= toBlock) { - const lastBlockInBatch = currentBlock + 98n // Batches of 99 - const effectiveLastBlock = - lastBlockInBatch > toBlock ? toBlock : lastBlockInBatch - + await loopThroughBlocks( + firstBlock, + lastBlock, + async (fromBlock, toBlock) => { // biome-ignore lint/suspicious/noExplicitAny: const promises: any[] = [] - for ( - let blockNumber = currentBlock; - blockNumber <= effectiveLastBlock; - blockNumber++ - ) { + for (let blockNumber = fromBlock; blockNumber <= toBlock; blockNumber++) { promises.push(viemClient.getBlock({ blockNumber: blockNumber })) } + const blocks = await Promise.all(promises) + const newBlockData: prisma.Evm_BlockData[] = [] + for (const block of blocks) { const timestamp = new Date(Number(block.timestamp) * 1000) - blockList.set(block.number, timestamp) - } - - console.log( - `Retrieved Block Data for ${currentBlock} - ${effectiveLastBlock}` - ) - currentBlock = effectiveLastBlock + 1n - } - }) - - // Prepare db transaction object - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] - const newBlockData: prisma.Evm_BlockData[] = [] + newBlockData.push({ + number: block.number, + timestamp + }) + } - for (const [number, timestamp] of blockList) { - newBlockData.push({ - number, - timestamp - }) - } + await prismaClient.evm_BlockData.createMany({ + data: newBlockData, + skipDuplicates: true + }) - dbTransactions.push( - prismaClient.evm_BlockData.createMany({ - data: newBlockData, - skipDuplicates: true - }) + console.log(`Retrieved Block Data for ${fromBlock} - ${toBlock}`) + }, + 99n ) - await bulkUpdateDbTransactions(dbTransactions) - - // Storing last sycned block - await saveLastSyncBlock(blockSyncKey, lastBlock) - - console.log('Seeded BlockData:', blockList.size) + console.log('Seeded Block Data:', Number(lastBlock - firstBlock)) } diff --git a/packages/seeder/src/events/seedEventLogs.ts b/packages/seeder/src/events/seedEventLogs.ts index 438270d3..9a23de33 100644 --- a/packages/seeder/src/events/seedEventLogs.ts +++ b/packages/seeder/src/events/seedEventLogs.ts @@ -1,34 +1,26 @@ +import prisma from '@prisma/client' import { parseAbiItem } from 'viem' import { getEigenContracts } from '../data/address' import { getViemClient } from '../utils/viemClient' import { + bulkUpdateDbTransactions, fetchLastSyncBlock, - loopThroughBlocks, - saveLastSyncBlock -} from '../utils/seeder' -import { - type TransactionLog, - type AVSMetadataURIUpdatedLog, - type OperatorAVSRegistrationStatusUpdatedLog, - type OperatorMetadataURIUpdatedLog, - type OperatorSharesIncreasedLog, - type OperatorSharesDecreasedLog, - type PodDeployedLog, - type StakerDelegatedLog, - type StakerUndelegatedLog, getBlockDataFromDb, - updateTableAVSMetadataURIUpdated, - updateTableOperatorAVSRegistrationStatusUpdated, - updateTableOperatorMetadataURIUpdated, - updateTableOperatorSharesIncreased, - updateTableOperatorSharesDecreased, - updateTablePodDeployed, - updateTableStakerDelegated, - updateTableStakerUndelegated -} from '../utils/events' + loopThroughBlocks +} from '../utils/seeder' +import { getPrismaClient } from '../utils/prismaClient' const blockSyncKey = 'lastSyncedBlock_logs' +export interface TransactionLog { + address: string + transactionHash: string + transactionIndex: number + blockNumber: bigint + blockHash: string + blockTime: Date +} + /** * Utility function to seed logs for 8 events * @@ -39,31 +31,20 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { console.log('Seeding Event Logs ...') const viemClient = getViemClient() + const prismaClient = getPrismaClient() - const avsMetadataURIUpdatedList: Map< - TransactionLog, - AVSMetadataURIUpdatedLog - > = new Map() - const operatorAVSRegistrationStatusUpdatedList: Map< - TransactionLog, - OperatorAVSRegistrationStatusUpdatedLog - > = new Map() - const operatorMetadataURIUpdatedList: Map< - TransactionLog, - OperatorMetadataURIUpdatedLog - > = new Map() - const operatorSharesIncreasedList: Map< - TransactionLog, - OperatorSharesIncreasedLog - > = new Map() - const operatorSharesDecreasedList: Map< - TransactionLog, - OperatorSharesDecreasedLog - > = new Map() - const podDeployedList: Map = new Map() - const stakerDelegatedList: Map = new Map() - const stakerUndelegatedList: Map = - new Map() + const logsAVSMetadataURIUpdated: prisma.EventLogs_AVSMetadataURIUpdated[] = [] + const logsOperatorMetadataURIUpdated: prisma.EventLogs_OperatorMetadataURIUpdated[] = + [] + const logsOperatorAVSRegistrationStatusUpdated: prisma.EventLogs_OperatorAVSRegistrationStatusUpdated[] = + [] + const logsPodDeployed: prisma.EventLogs_PodDeployed[] = [] + const logsOperatorSharesDecreased: prisma.EventLogs_OperatorSharesDecreased[] = + [] + const logsOperatorSharesIncreased: prisma.EventLogs_OperatorSharesIncreased[] = + [] + const logsStakerDelegated: prisma.EventLogs_StakerDelegated[] = [] + const logsStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] const firstBlock = fromBlock ? fromBlock @@ -73,6 +54,9 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { // Loop through evm logs for all 8 events from 3 contracts await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + try { const logs = await viemClient.getLogs({ address: [ @@ -125,149 +109,148 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { switch (log.eventName) { case 'AVSMetadataURIUpdated': { - const eventData: AVSMetadataURIUpdatedLog = { - avs: log.args.avs, - metadataURI: log.args.metadataURI - } - avsMetadataURIUpdatedList.set(transactionData, eventData) + logsAVSMetadataURIUpdated.push({ + ...transactionData, + avs: String(log.args.avs), + metadataURI: String(log.args.metadataURI) + }) break } case 'OperatorAVSRegistrationStatusUpdated': { - const eventData: OperatorAVSRegistrationStatusUpdatedLog = { - operator: log.args.operator, - avs: log.args.avs, - status: log.args.status || 0 - } - operatorAVSRegistrationStatusUpdatedList.set( - transactionData, - eventData - ) + logsOperatorAVSRegistrationStatusUpdated.push({ + ...transactionData, + operator: String(log.args.operator), + avs: String(log.args.avs), + status: Number(log.args.status) + }) break } case 'OperatorMetadataURIUpdated': { - const eventData: OperatorMetadataURIUpdatedLog = { - operator: log.args.operator, - metadataURI: log.args.metadataURI - } - operatorMetadataURIUpdatedList.set(transactionData, eventData) + logsOperatorMetadataURIUpdated.push({ + ...transactionData, + operator: String(log.args.operator), + metadataURI: String(log.args.metadataURI) + }) break } case 'OperatorSharesIncreased': { - const shares = log.args.shares - if (!shares) continue - - const eventData: OperatorSharesIncreasedLog = { - operator: log.args.operator, - staker: log.args.staker, - strategy: log.args.strategy, - shares: shares.toString() - } - operatorSharesIncreasedList.set(transactionData, eventData) + logsOperatorSharesIncreased.push({ + ...transactionData, + operator: String(log.args.operator), + staker: String(log.args.staker), + strategy: String(log.args.strategy), + shares: String(log.args.shares) + }) break } case 'OperatorSharesDecreased': { - const shares = log.args.shares - if (!shares) continue - - const eventData: OperatorSharesDecreasedLog = { - operator: log.args.operator, - staker: log.args.staker, - strategy: log.args.strategy, - shares: shares.toString() - } - operatorSharesDecreasedList.set(transactionData, eventData) + logsOperatorSharesDecreased.push({ + ...transactionData, + operator: String(log.args.operator), + staker: String(log.args.staker), + strategy: String(log.args.strategy), + shares: String(log.args.shares) + }) break } case 'PodDeployed': { - const eventData: PodDeployedLog = { - eigenPod: log.args.eigenPod, - podOwner: log.args.podOwner - } - podDeployedList.set(transactionData, eventData) + logsPodDeployed.push({ + ...transactionData, + eigenPod: String(log.args.eigenPod), + podOwner: String(log.args.podOwner) + }) break } case 'StakerDelegated': { - const staker = log.args.staker - if (!staker) continue - - const eventData: StakerDelegatedLog = { - staker: staker, - operator: log.args.operator - } - stakerDelegatedList.set(transactionData, eventData) + logsStakerDelegated.push({ + ...transactionData, + staker: String(log.args.staker), + operator: String(log.args.operator) + }) break } case 'StakerUndelegated': { - const eventData: StakerUndelegatedLog = { - staker: log.args.staker, - operator: log.args.operator - } - stakerUndelegatedList.set(transactionData, eventData) + logsStakerUndelegated.push({ + ...transactionData, + staker: String(log.args.staker), + operator: String(log.args.operator) + }) } } } - console.log( - `Event logs registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` + + // Update logs to the database + + dbTransactions.push( + prismaClient.eventLogs_AVSMetadataURIUpdated.createMany({ + data: logsAVSMetadataURIUpdated, + skipDuplicates: true + }) + ) + + dbTransactions.push( + prismaClient.eventLogs_OperatorMetadataURIUpdated.createMany({ + data: logsOperatorMetadataURIUpdated, + skipDuplicates: true + }) + ) + + dbTransactions.push( + prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.createMany({ + data: logsOperatorAVSRegistrationStatusUpdated, + skipDuplicates: true + }) + ) + + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesDecreased.createMany({ + data: logsOperatorSharesDecreased, + skipDuplicates: true + }) + ) + + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesIncreased.createMany({ + data: logsOperatorSharesIncreased, + skipDuplicates: true + }) + ) + + dbTransactions.push( + prismaClient.eventLogs_StakerDelegated.createMany({ + data: logsStakerDelegated, + skipDuplicates: true + }) ) - } catch (error) {} - }) - // Update all EventLog tables with the respective event log data - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] + dbTransactions.push( + prismaClient.eventLogs_StakerUndelegated.createMany({ + data: logsStakerUndelegated, + skipDuplicates: true + }) + ) - await updateTableAVSMetadataURIUpdated( - dbTransactions, - avsMetadataURIUpdatedList - ) - await updateTableOperatorAVSRegistrationStatusUpdated( - dbTransactions, - operatorAVSRegistrationStatusUpdatedList - ) - await updateTableOperatorMetadataURIUpdated( - dbTransactions, - operatorMetadataURIUpdatedList - ) - await updateTableOperatorSharesIncreased( - dbTransactions, - operatorSharesIncreasedList - ) - await updateTableOperatorSharesDecreased( - dbTransactions, - operatorSharesDecreasedList - ) - await updateTablePodDeployed(dbTransactions, podDeployedList) - await updateTableStakerDelegated(dbTransactions, stakerDelegatedList) - await updateTableStakerUndelegated(dbTransactions, stakerUndelegatedList) + // Store last synced block + dbTransactions.push( + prismaClient.settings.upsert({ + where: { key: blockSyncKey }, + update: { value: Number(toBlock) }, + create: { key: blockSyncKey, value: Number(toBlock) } + }) + ) - // Store last synced block - await saveLastSyncBlock(blockSyncKey, lastBlock) + await bulkUpdateDbTransactions(dbTransactions) - console.log('Seeded AVSMetadataURIUpdated:', avsMetadataURIUpdatedList.size) - console.log( - 'Seeded OperatorAVSRegistrationStatusUpdated:', - operatorAVSRegistrationStatusUpdatedList.size - ) - console.log( - 'Seeded OperatorMetadataURIUpdated:', - operatorMetadataURIUpdatedList.size - ) - console.log( - 'Seeded OperatorSharesIncreased:', - operatorSharesIncreasedList.size - ) - console.log( - 'Seeded OperatorSharesDecreased:', - operatorSharesDecreasedList.size - ) - console.log('Seeded PodDeployed:', podDeployedList.size) - console.log('Seeded StakerDelegated:', stakerDelegatedList.size) - console.log('Seeded StakerUndelegated:', stakerUndelegatedList.size) + console.log( + `Event logs registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` + ) + } catch (error) {} + }) } diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 73cd17fe..5bd73333 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -34,28 +34,28 @@ async function seedEventLogsLoop() { console.log(error) } - await delay(90) // Wait for 1.5 minutes (90 seconds) + await delay(60) } } async function seedEigenDataLoop() { + await delay(60) + while (true) { try { const targetBlock = await fetchLastLogBlock() - if (!targetBlock) { - delay(60) - continue - } - console.log('Seeding Eigen Data ...', targetBlock) + if (targetBlock) { + console.log('Seeding Eigen Data ...', targetBlock) - await seedAvs(targetBlock) - await seedOperators(targetBlock) - await seedAvsOperators(targetBlock) - await seedStakers(targetBlock) - await seedOperatorShares(targetBlock) - await seedQueuedWithdrawals(targetBlock) - await seedCompletedWithdrawals(targetBlock) + await seedAvs(targetBlock) + await seedOperators(targetBlock) + await seedAvsOperators(targetBlock) + await seedStakers(targetBlock) + await seedOperatorShares(targetBlock) + await seedQueuedWithdrawals(targetBlock) + await seedCompletedWithdrawals(targetBlock) + } } catch (error) { console.log('Failed to seed AVS and Opeartors at:', Date.now()) console.log(error) @@ -71,15 +71,13 @@ async function seedEigenPodValidators() { while (true) { try { const targetBlock = await fetchLastLogBlock() - if (!targetBlock) { - delay(60) - continue - } - console.log('Seeding Eigen Pods Data ...', targetBlock) + if (targetBlock) { + console.log('Seeding Eigen Pods Data ...', targetBlock) - await seedPods(targetBlock) - await seedValidators() + await seedPods(targetBlock) + await seedValidators() + } } catch (error) { console.log('Failed to seed validators at block:', Date.now()) } diff --git a/packages/seeder/src/utils/events.ts b/packages/seeder/src/utils/events.ts index 44183a5d..1c642f5c 100644 --- a/packages/seeder/src/utils/events.ts +++ b/packages/seeder/src/utils/events.ts @@ -1,9 +1,6 @@ -import type prisma from '@prisma/client' import { getPrismaClient } from '../utils/prismaClient' -import { bulkUpdateDbTransactions } from '../utils/seeder' - -const prismaClient = getPrismaClient() +// TBD export interface TransactionLog { address: string transactionHash: string @@ -13,423 +10,7 @@ export interface TransactionLog { blockTime: Date } -export interface AVSMetadataURIUpdatedLog { - avs: `0x${string}` | undefined - metadataURI: string | undefined -} - -export interface OperatorAVSRegistrationStatusUpdatedLog { - operator: `0x${string}` | undefined - avs: `0x${string}` | undefined - status: number -} - -export interface OperatorMetadataURIUpdatedLog { - operator: `0x${string}` | undefined - metadataURI: string | undefined -} - -export interface OperatorSharesIncreasedLog { - operator: `0x${string}` | undefined - staker: `0x${string}` | undefined - strategy: `0x${string}` | undefined - shares: string -} - -export interface OperatorSharesDecreasedLog { - operator: `0x${string}` | undefined - staker: `0x${string}` | undefined - strategy: `0x${string}` | undefined - shares: string -} - -export interface PodDeployedLog { - eigenPod: `0x${string}` | undefined - podOwner: `0x${string}` | undefined -} - -export interface StakerDelegatedLog { - staker: `0x${string}` | undefined - operator: `0x${string}` | undefined -} - -export interface StakerUndelegatedLog { - staker: `0x${string}` | undefined - operator: `0x${string}` | undefined -} - -export async function updateTableAVSMetadataURIUpdated( - // biome-ignore lint/suspicious/noExplicitAny: - dbTransactions: any[], - avsMetadataURIUpdatedList: Map -) { - try { - const newAvsMetadataURIUpdated: prisma.EventLogs_AVSMetadataURIUpdated[] = - [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { avs, metadataURI } - ] of avsMetadataURIUpdatedList) { - newAvsMetadataURIUpdated.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - avs, - metadataURI - }) - } - - dbTransactions.push( - prismaClient.eventLogs_AVSMetadataURIUpdated.createMany({ - data: newAvsMetadataURIUpdated, - skipDuplicates: true - }) - ) - } catch {} - - await bulkUpdateDbTransactions(dbTransactions) -} - -export async function updateTableOperatorAVSRegistrationStatusUpdated( - // biome-ignore lint/suspicious/noExplicitAny: - dbTransactions: any[], - operatorAVSRegistrationStatusUpdatedList: Map< - TransactionLog, - OperatorAVSRegistrationStatusUpdatedLog - > -) { - try { - const newOperatorAVSRegistrationStatusUpdated: prisma.EventLogs_OperatorAVSRegistrationStatusUpdated[] = - [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, avs, status } - ] of operatorAVSRegistrationStatusUpdatedList) { - newOperatorAVSRegistrationStatusUpdated.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - avs, - status - }) - } - - dbTransactions.push( - prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.createMany({ - data: newOperatorAVSRegistrationStatusUpdated, - skipDuplicates: true - }) - ) - } catch {} - - await bulkUpdateDbTransactions(dbTransactions) -} - -export async function updateTableOperatorMetadataURIUpdated( - // biome-ignore lint/suspicious/noExplicitAny: - dbTransactions: any[], - operatorMetadataURIUpdatedList: Map< - TransactionLog, - OperatorMetadataURIUpdatedLog - > -) { - try { - const newOperatorMetadataURIUpdated: prisma.EventLogs_OperatorMetadataURIUpdated[] = - [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, metadataURI } - ] of operatorMetadataURIUpdatedList) { - newOperatorMetadataURIUpdated.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - metadataURI - }) - } - - dbTransactions.push( - prismaClient.eventLogs_OperatorMetadataURIUpdated.createMany({ - data: newOperatorMetadataURIUpdated, - skipDuplicates: true - }) - ) - } catch {} - - await bulkUpdateDbTransactions(dbTransactions) -} - -export async function updateTableOperatorSharesIncreased( - // biome-ignore lint/suspicious/noExplicitAny: - dbTransactions: any[], - operatorSharesIncreasedList: Map -) { - try { - const newOperatorSharesIncreased: prisma.EventLogs_OperatorSharesIncreased[] = - [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, staker, strategy, shares } - ] of operatorSharesIncreasedList) { - newOperatorSharesIncreased.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - staker, - strategy, - shares - }) - } - - dbTransactions.push( - prismaClient.eventLogs_OperatorSharesIncreased.createMany({ - data: newOperatorSharesIncreased, - skipDuplicates: true - }) - ) - } catch {} - - await bulkUpdateDbTransactions(dbTransactions) -} - -export async function updateTableOperatorSharesDecreased( - // biome-ignore lint/suspicious/noExplicitAny: - dbTransactions: any[], - operatorSharesDecreasedList: Map -) { - try { - const newOperatorSharesDecreased: prisma.EventLogs_OperatorSharesDecreased[] = - [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { operator, staker, strategy, shares } - ] of operatorSharesDecreasedList) { - newOperatorSharesDecreased.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - operator, - staker, - strategy, - shares - }) - } - - dbTransactions.push( - prismaClient.eventLogs_OperatorSharesDecreased.createMany({ - data: newOperatorSharesDecreased, - skipDuplicates: true - }) - ) - } catch {} - - await bulkUpdateDbTransactions(dbTransactions) -} - -export async function updateTablePodDeployed( - // biome-ignore lint/suspicious/noExplicitAny: - dbTransactions: any[], - podDeployedList: Map -) { - try { - const newPodDeployed: prisma.EventLogs_PodDeployed[] = [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { eigenPod, podOwner } - ] of podDeployedList) { - newPodDeployed.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - eigenPod, - podOwner - }) - } - - dbTransactions.push( - prismaClient.eventLogs_PodDeployed.createMany({ - data: newPodDeployed, - skipDuplicates: true - }) - ) - } catch {} - - await bulkUpdateDbTransactions(dbTransactions) -} - -export async function updateTableStakerDelegated( - // biome-ignore lint/suspicious/noExplicitAny: - dbTransactions: any[], - stakerDelegatedList: Map -) { - try { - const newStakerDelegated: prisma.EventLogs_StakerDelegated[] = [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { staker, operator } - ] of stakerDelegatedList) { - newStakerDelegated.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - staker, - operator - }) - } - - dbTransactions.push( - prismaClient.eventLogs_StakerDelegated.createMany({ - data: newStakerDelegated, - skipDuplicates: true - }) - ) - } catch {} - - await bulkUpdateDbTransactions(dbTransactions) -} - -export async function updateTableStakerUndelegated( - // biome-ignore lint/suspicious/noExplicitAny: - dbTransactions: any[], - stakerUndelegatedList: Map -) { - try { - const newStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] - - for (const [ - { - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime - }, - { staker, operator } - ] of stakerUndelegatedList) { - newStakerUndelegated.push({ - address, - transactionHash, - transactionIndex, - blockNumber, - blockHash, - blockTime, - staker, - operator - }) - } - - dbTransactions.push( - prismaClient.eventLogs_StakerUndelegated.createMany({ - data: newStakerUndelegated, - skipDuplicates: true - }) - ) - } catch {} - - await bulkUpdateDbTransactions(dbTransactions) -} - -export async function getBlockDataFromDb(fromBlock: bigint, toBlock: bigint) { - const blockData = await prismaClient.evm_BlockData.findMany({ - where: { - number: { - gte: BigInt(fromBlock), - lte: BigInt(toBlock) - } - }, - select: { - number: true, - timestamp: true - }, - orderBy: { - number: 'asc' - } - }) - - return new Map(blockData.map((block) => [block.number, block.timestamp])) -} - +// TBD export async function fetchLastLogBlock(): Promise { const prismaClient = getPrismaClient() diff --git a/packages/seeder/src/utils/seeder.ts b/packages/seeder/src/utils/seeder.ts index 67300888..77f3cfa1 100644 --- a/packages/seeder/src/utils/seeder.ts +++ b/packages/seeder/src/utils/seeder.ts @@ -15,13 +15,15 @@ export const baseBlock = export async function loopThroughBlocks( firstBlock: bigint, lastBlock: bigint, - cb: (fromBlock: bigint, toBlock: bigint) => Promise + cb: (fromBlock: bigint, toBlock: bigint) => Promise, + defaultBatchSize?: bigint, ) { + const batchSize = defaultBatchSize ? defaultBatchSize : 9999n let currentBlock = firstBlock let nextBlock = firstBlock while (nextBlock < lastBlock) { - nextBlock = currentBlock + 4999n + nextBlock = currentBlock + batchSize if (nextBlock >= lastBlock) nextBlock = lastBlock await cb(currentBlock, nextBlock) @@ -70,3 +72,25 @@ export async function saveLastSyncBlock(key: string, blockNumber: bigint) { create: { key: key, value: Number(blockNumber) } }) } + +export async function getBlockDataFromDb(fromBlock: bigint, toBlock: bigint) { + const prismaClient = getPrismaClient() + + const blockData = await prismaClient.evm_BlockData.findMany({ + where: { + number: { + gte: BigInt(fromBlock), + lte: BigInt(toBlock) + } + }, + select: { + number: true, + timestamp: true + }, + orderBy: { + number: 'asc' + } + }) + + return new Map(blockData.map((block) => [block.number, block.timestamp])) +} \ No newline at end of file From 99b96e9d19bed061995bcb83e89fc720afed5b9f Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Thu, 6 Jun 2024 13:22:10 +0530 Subject: [PATCH 29/62] normalized log data structure --- packages/seeder/src/seedStakers.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index 6a4daca1..52b93130 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -45,7 +45,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } }) .then((logs) => - logs.map((log) => ({ ...log, eventName: 'StakerDelegated' })) + logs.map((log) => ({ ...log, shares: '', strategy: '', eventName: 'StakerDelegated' })) ) const logsStakerUndelegated = await prismaClient.eventLogs_StakerUndelegated @@ -58,7 +58,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } }) .then((logs) => - logs.map((log) => ({ ...log, eventName: 'StakerUndelegated' })) + logs.map((log) => ({ ...log, shares: '', strategy: '', eventName: 'StakerUndelegated' })) ) const logsOperatorSharesIncreased = @@ -72,7 +72,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } }) .then((logs) => - logs.map((log) => ({ ...log, eventName: 'OperatorSharesIncreased' })) + logs.map((log) => ({ ...log, shares: log.shares, strategy: log.strategy, eventName: 'OperatorSharesIncreased' })) ) const logsOperatorSharesDecreased = @@ -86,7 +86,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } }) .then((logs) => - logs.map((log) => ({ ...log, eventName: 'OperatorSharesDecreased' })) + logs.map((log) => ({ ...log, shares: log.shares, strategy: log.strategy, eventName: 'OperatorSharesDecreased' })) ) const logs = [ From da1d7d8dcbf4f338536b229db15905f2d1ab296d Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Thu, 6 Jun 2024 13:52:53 +0530 Subject: [PATCH 30/62] add depsit event to logs seeding --- packages/prisma/schema.prisma | 18 +++++++++++++++++ packages/seeder/src/events/seedEventLogs.ts | 22 +++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 6b6b5c8f..ed14c1ce 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -305,6 +305,24 @@ model EventLogs_OperatorSharesDecreased { @@index([staker, operator]) } +model EventLogs_Deposit { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + staker String + token String + strategy String + shares String + + @@id([transactionHash, transactionIndex]) + @@index([staker, strategy]) +} + // Misc model Evm_BlockData { diff --git a/packages/seeder/src/events/seedEventLogs.ts b/packages/seeder/src/events/seedEventLogs.ts index 9a23de33..81e6fb21 100644 --- a/packages/seeder/src/events/seedEventLogs.ts +++ b/packages/seeder/src/events/seedEventLogs.ts @@ -45,6 +45,7 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { [] const logsStakerDelegated: prisma.EventLogs_StakerDelegated[] = [] const logsStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] + const logsDeposit: prisma.EventLogs_Deposit[] = [] const firstBlock = fromBlock ? fromBlock @@ -88,6 +89,9 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { ), parseAbiItem( 'event StakerUndelegated(address indexed staker, address indexed operator)' + ), + parseAbiItem( + 'event Deposit(address staker, address token, address strategy, uint256 shares)' ) ], fromBlock, @@ -182,6 +186,17 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { staker: String(log.args.staker), operator: String(log.args.operator) }) + break + } + + case 'Deposit': { + logsDeposit.push({ + ...transactionData, + staker: String(log.args.staker), + token: String(log.args.token), + strategy: String(log.args.strategy), + shares: String(log.args.shares) + }) } } } @@ -237,6 +252,13 @@ export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { }) ) + dbTransactions.push( + prismaClient.eventLogs_Deposit.createMany({ + data: logsDeposit, + skipDuplicates: true + }) + ) + // Store last synced block dbTransactions.push( prismaClient.settings.upsert({ From 348723d5f8d4aec029fe999e62352e721f5e590c Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Thu, 6 Jun 2024 13:59:10 +0530 Subject: [PATCH 31/62] removed viemclient --- packages/seeder/src/seedAvs.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 7063eee6..16c9d033 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -1,7 +1,6 @@ import type prisma from '@prisma/client' import { isValidMetadataUrl, validateMetadata } from './utils/metadata' import { type EntityMetadata, defaultMetadata } from './utils/metadata' -import { getViemClient } from './utils/viemClient' import { getPrismaClient } from './utils/prismaClient' import { fetchLastLogBlock } from './utils/events' import { @@ -30,7 +29,6 @@ interface AvsEntryRecord { export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { console.log('Seeding AVS ...') - const viemClient = getViemClient() const prismaClient = getPrismaClient() const avsList: Map = new Map() From d8378053e67a946eae99f04c30e5cb1cda159b1e Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Thu, 6 Jun 2024 18:18:50 +0530 Subject: [PATCH 32/62] moved from a centralized logs seeder to an individual logs seeder per event set --- packages/prisma/schema.prisma | 18 -- .../src/{events => blocks}/seedBlockData.ts | 0 packages/seeder/src/events/seedEventLogs.ts | 278 ------------------ .../seeder/src/events/seedLogsAVSMetadata.ts | 94 ++++++ .../seedLogsOperatorAVSRegistrationStatus.ts | 95 ++++++ .../src/events/seedLogsOperatorMetadata.ts | 94 ++++++ .../src/events/seedLogsOperatorShares.ts | 123 ++++++++ .../seeder/src/events/seedLogsPodDeployed.ts | 94 ++++++ .../src/events/seedLogsStakerDelegation.ts | 119 ++++++++ packages/seeder/src/index.ts | 53 ++-- packages/seeder/src/seedAvs.ts | 34 ++- packages/seeder/src/seedAvsOperators.ts | 8 +- packages/seeder/src/seedOperatorShares.ts | 8 +- packages/seeder/src/seedOperators.ts | 34 ++- packages/seeder/src/seedPods.ts | 8 +- packages/seeder/src/seedStakers.ts | 8 +- packages/seeder/src/utils/events.ts | 24 -- 17 files changed, 720 insertions(+), 372 deletions(-) rename packages/seeder/src/{events => blocks}/seedBlockData.ts (100%) delete mode 100644 packages/seeder/src/events/seedEventLogs.ts create mode 100644 packages/seeder/src/events/seedLogsAVSMetadata.ts create mode 100644 packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts create mode 100644 packages/seeder/src/events/seedLogsOperatorMetadata.ts create mode 100644 packages/seeder/src/events/seedLogsOperatorShares.ts create mode 100644 packages/seeder/src/events/seedLogsPodDeployed.ts create mode 100644 packages/seeder/src/events/seedLogsStakerDelegation.ts delete mode 100644 packages/seeder/src/utils/events.ts diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index ed14c1ce..6b6b5c8f 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -305,24 +305,6 @@ model EventLogs_OperatorSharesDecreased { @@index([staker, operator]) } -model EventLogs_Deposit { - address String - - transactionHash String - transactionIndex Int - blockNumber BigInt - blockHash String - blockTime DateTime - - staker String - token String - strategy String - shares String - - @@id([transactionHash, transactionIndex]) - @@index([staker, strategy]) -} - // Misc model Evm_BlockData { diff --git a/packages/seeder/src/events/seedBlockData.ts b/packages/seeder/src/blocks/seedBlockData.ts similarity index 100% rename from packages/seeder/src/events/seedBlockData.ts rename to packages/seeder/src/blocks/seedBlockData.ts diff --git a/packages/seeder/src/events/seedEventLogs.ts b/packages/seeder/src/events/seedEventLogs.ts deleted file mode 100644 index 81e6fb21..00000000 --- a/packages/seeder/src/events/seedEventLogs.ts +++ /dev/null @@ -1,278 +0,0 @@ -import prisma from '@prisma/client' -import { parseAbiItem } from 'viem' -import { getEigenContracts } from '../data/address' -import { getViemClient } from '../utils/viemClient' -import { - bulkUpdateDbTransactions, - fetchLastSyncBlock, - getBlockDataFromDb, - loopThroughBlocks -} from '../utils/seeder' -import { getPrismaClient } from '../utils/prismaClient' - -const blockSyncKey = 'lastSyncedBlock_logs' - -export interface TransactionLog { - address: string - transactionHash: string - transactionIndex: number - blockNumber: bigint - blockHash: string - blockTime: Date -} - -/** - * Utility function to seed logs for 8 events - * - * @param fromBlock - * @param toBlock - */ -export async function seedEventLogs(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding Event Logs ...') - - const viemClient = getViemClient() - const prismaClient = getPrismaClient() - - const logsAVSMetadataURIUpdated: prisma.EventLogs_AVSMetadataURIUpdated[] = [] - const logsOperatorMetadataURIUpdated: prisma.EventLogs_OperatorMetadataURIUpdated[] = - [] - const logsOperatorAVSRegistrationStatusUpdated: prisma.EventLogs_OperatorAVSRegistrationStatusUpdated[] = - [] - const logsPodDeployed: prisma.EventLogs_PodDeployed[] = [] - const logsOperatorSharesDecreased: prisma.EventLogs_OperatorSharesDecreased[] = - [] - const logsOperatorSharesIncreased: prisma.EventLogs_OperatorSharesIncreased[] = - [] - const logsStakerDelegated: prisma.EventLogs_StakerDelegated[] = [] - const logsStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] - const logsDeposit: prisma.EventLogs_Deposit[] = [] - - const firstBlock = fromBlock - ? fromBlock - : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - const blockData = await getBlockDataFromDb(firstBlock, lastBlock) - - // Loop through evm logs for all 8 events from 3 contracts - await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] - - try { - const logs = await viemClient.getLogs({ - address: [ - getEigenContracts().AVSDirectory, - getEigenContracts().DelegationManager, - getEigenContracts().EigenPodManager - ], - events: [ - parseAbiItem( - 'event AVSMetadataURIUpdated(address indexed avs, string metadataURI)' - ), - parseAbiItem( - 'event OperatorAVSRegistrationStatusUpdated(address indexed operator, address indexed avs, uint8 status)' - ), - parseAbiItem( - 'event OperatorMetadataURIUpdated(address indexed operator, string metadataURI)' - ), - parseAbiItem( - 'event OperatorSharesIncreased(address indexed operator, address staker, address strategy, uint256 shares)' - ), - parseAbiItem( - 'event OperatorSharesDecreased(address indexed operator, address staker, address strategy, uint256 shares)' - ), - parseAbiItem( - 'event PodDeployed(address indexed eigenPod, address indexed podOwner)' - ), - parseAbiItem( - 'event StakerDelegated(address indexed staker, address indexed operator)' - ), - parseAbiItem( - 'event StakerUndelegated(address indexed staker, address indexed operator)' - ), - parseAbiItem( - 'event Deposit(address staker, address token, address strategy, uint256 shares)' - ) - ], - fromBlock, - toBlock - }) - - // For each event, setup different lists containing event data - for (const l in logs) { - const log = logs[l] - - const transactionData: TransactionLog = { - address: log.address, - transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, - blockNumber: BigInt(log.blockNumber), - blockHash: log.blockHash, - blockTime: blockData.get(log.blockNumber) || new Date(0) - } - - switch (log.eventName) { - case 'AVSMetadataURIUpdated': { - logsAVSMetadataURIUpdated.push({ - ...transactionData, - avs: String(log.args.avs), - metadataURI: String(log.args.metadataURI) - }) - break - } - - case 'OperatorAVSRegistrationStatusUpdated': { - logsOperatorAVSRegistrationStatusUpdated.push({ - ...transactionData, - operator: String(log.args.operator), - avs: String(log.args.avs), - status: Number(log.args.status) - }) - break - } - - case 'OperatorMetadataURIUpdated': { - logsOperatorMetadataURIUpdated.push({ - ...transactionData, - operator: String(log.args.operator), - metadataURI: String(log.args.metadataURI) - }) - break - } - - case 'OperatorSharesIncreased': { - logsOperatorSharesIncreased.push({ - ...transactionData, - operator: String(log.args.operator), - staker: String(log.args.staker), - strategy: String(log.args.strategy), - shares: String(log.args.shares) - }) - break - } - - case 'OperatorSharesDecreased': { - logsOperatorSharesDecreased.push({ - ...transactionData, - operator: String(log.args.operator), - staker: String(log.args.staker), - strategy: String(log.args.strategy), - shares: String(log.args.shares) - }) - break - } - - case 'PodDeployed': { - logsPodDeployed.push({ - ...transactionData, - eigenPod: String(log.args.eigenPod), - podOwner: String(log.args.podOwner) - }) - break - } - - case 'StakerDelegated': { - logsStakerDelegated.push({ - ...transactionData, - staker: String(log.args.staker), - operator: String(log.args.operator) - }) - break - } - - case 'StakerUndelegated': { - logsStakerUndelegated.push({ - ...transactionData, - staker: String(log.args.staker), - operator: String(log.args.operator) - }) - break - } - - case 'Deposit': { - logsDeposit.push({ - ...transactionData, - staker: String(log.args.staker), - token: String(log.args.token), - strategy: String(log.args.strategy), - shares: String(log.args.shares) - }) - } - } - } - - // Update logs to the database - - dbTransactions.push( - prismaClient.eventLogs_AVSMetadataURIUpdated.createMany({ - data: logsAVSMetadataURIUpdated, - skipDuplicates: true - }) - ) - - dbTransactions.push( - prismaClient.eventLogs_OperatorMetadataURIUpdated.createMany({ - data: logsOperatorMetadataURIUpdated, - skipDuplicates: true - }) - ) - - dbTransactions.push( - prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.createMany({ - data: logsOperatorAVSRegistrationStatusUpdated, - skipDuplicates: true - }) - ) - - dbTransactions.push( - prismaClient.eventLogs_OperatorSharesDecreased.createMany({ - data: logsOperatorSharesDecreased, - skipDuplicates: true - }) - ) - - dbTransactions.push( - prismaClient.eventLogs_OperatorSharesIncreased.createMany({ - data: logsOperatorSharesIncreased, - skipDuplicates: true - }) - ) - - dbTransactions.push( - prismaClient.eventLogs_StakerDelegated.createMany({ - data: logsStakerDelegated, - skipDuplicates: true - }) - ) - - dbTransactions.push( - prismaClient.eventLogs_StakerUndelegated.createMany({ - data: logsStakerUndelegated, - skipDuplicates: true - }) - ) - - dbTransactions.push( - prismaClient.eventLogs_Deposit.createMany({ - data: logsDeposit, - skipDuplicates: true - }) - ) - - // Store last synced block - dbTransactions.push( - prismaClient.settings.upsert({ - where: { key: blockSyncKey }, - update: { value: Number(toBlock) }, - create: { key: blockSyncKey, value: Number(toBlock) } - }) - ) - - await bulkUpdateDbTransactions(dbTransactions) - - console.log( - `Event logs registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` - ) - } catch (error) {} - }) -} diff --git a/packages/seeder/src/events/seedLogsAVSMetadata.ts b/packages/seeder/src/events/seedLogsAVSMetadata.ts new file mode 100644 index 00000000..da5ae916 --- /dev/null +++ b/packages/seeder/src/events/seedLogsAVSMetadata.ts @@ -0,0 +1,94 @@ +import prisma from '@prisma/client' +import { parseAbiItem } from 'viem' +import { getEigenContracts } from '../data/address' +import { getViemClient } from '../utils/viemClient' +import { + bulkUpdateDbTransactions, + fetchLastSyncBlock, + getBlockDataFromDb, + loopThroughBlocks +} from '../utils/seeder' +import { getPrismaClient } from '../utils/prismaClient' + +const blockSyncKeyLogs = 'lastSyncedBlock_logs_avs' + +/** + * Utility function to seed event logs + * + * @param fromBlock + * @param toBlock + */ +export async function seedLogsAVSMetadata(toBlock?: bigint, fromBlock?: bigint) { + console.log('Seeding Event Logs for AVSMetadataURIUpdated...') + + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + const viemClient = getViemClient() + const prismaClient = getPrismaClient() + + const logsAVSMetadataURIUpdated: prisma.EventLogs_AVSMetadataURIUpdated[] = [] + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + try { + const logs = await viemClient.getLogs({ + address: [ + getEigenContracts().AVSDirectory + ], + events: [ + parseAbiItem( + 'event AVSMetadataURIUpdated(address indexed avs, string metadataURI)' + ) + ], + fromBlock, + toBlock + }) + + // Setup a list containing event data + for (const l in logs) { + const log = logs[l] + + logsAVSMetadataURIUpdated.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + avs: String(log.args.avs), + metadataURI: String(log.args.metadataURI) + }) + } + + dbTransactions.push( + prismaClient.eventLogs_AVSMetadataURIUpdated.createMany({ + data: logsAVSMetadataURIUpdated, + skipDuplicates: true + }) + ) + + // Store last synced block + dbTransactions.push( + prismaClient.settings.upsert({ + where: { key: blockSyncKeyLogs }, + update: { value: Number(toBlock) }, + create: { key: blockSyncKeyLogs, value: Number(toBlock) } + }) + ) + + // Update database + await bulkUpdateDbTransactions(dbTransactions) + } catch (error) {} + }) + + console.log( + `Seeded AVSMetadataURIUpdated logs between blocks ${firstBlock} ${lastBlock}: ${logsAVSMetadataURIUpdated.length}` + ) +} \ No newline at end of file diff --git a/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts b/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts new file mode 100644 index 00000000..f81ebc13 --- /dev/null +++ b/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts @@ -0,0 +1,95 @@ +import prisma from '@prisma/client' +import { parseAbiItem } from 'viem' +import { getEigenContracts } from '../data/address' +import { getViemClient } from '../utils/viemClient' +import { + bulkUpdateDbTransactions, + fetchLastSyncBlock, + getBlockDataFromDb, + loopThroughBlocks +} from '../utils/seeder' +import { getPrismaClient } from '../utils/prismaClient' + +const blockSyncKeyLogs = 'lastSyncedBlock_logs_avsOperators' + +/** + * Utility function to seed event logs + * + * @param fromBlock + * @param toBlock + */ +export async function seedLogsOperatorAVSRegistrationStatus(toBlock?: bigint, fromBlock?: bigint) { + console.log('Seeding Event Logs for OperatorAVSRegistrationStatusUpdated...') + + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + const viemClient = getViemClient() + const prismaClient = getPrismaClient() + + const logsOperatorAVSRegistrationStatusUpdated: prisma.EventLogs_OperatorAVSRegistrationStatusUpdated[] = [] + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + try { + const logs = await viemClient.getLogs({ + address: [ + getEigenContracts().AVSDirectory + ], + events: [ + parseAbiItem( + 'event OperatorAVSRegistrationStatusUpdated(address indexed operator, address indexed avs, uint8 status)' + ) + ], + fromBlock, + toBlock + }) + + // Setup a list containing event data + for (const l in logs) { + const log = logs[l] + + logsOperatorAVSRegistrationStatusUpdated.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + operator: String(log.args.operator), + avs: String(log.args.avs), + status: Number(log.args.status) + }) + } + + dbTransactions.push( + prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.createMany({ + data: logsOperatorAVSRegistrationStatusUpdated, + skipDuplicates: true + }) + ) + + // Store last synced block + dbTransactions.push( + prismaClient.settings.upsert({ + where: { key: blockSyncKeyLogs }, + update: { value: Number(toBlock) }, + create: { key: blockSyncKeyLogs, value: Number(toBlock) } + }) + ) + + // Update database + await bulkUpdateDbTransactions(dbTransactions) + } catch (error) {} + }) + + console.log( + `Seeded OperatorAVSRegistrationStatusUpdated logs between blocks ${firstBlock} ${lastBlock}: ${logsOperatorAVSRegistrationStatusUpdated.length}` + ) +} \ No newline at end of file diff --git a/packages/seeder/src/events/seedLogsOperatorMetadata.ts b/packages/seeder/src/events/seedLogsOperatorMetadata.ts new file mode 100644 index 00000000..e31db3cd --- /dev/null +++ b/packages/seeder/src/events/seedLogsOperatorMetadata.ts @@ -0,0 +1,94 @@ +import prisma from '@prisma/client' +import { parseAbiItem } from 'viem' +import { getEigenContracts } from '../data/address' +import { getViemClient } from '../utils/viemClient' +import { + bulkUpdateDbTransactions, + fetchLastSyncBlock, + getBlockDataFromDb, + loopThroughBlocks +} from '../utils/seeder' +import { getPrismaClient } from '../utils/prismaClient' + +const blockSyncKeyLogs = 'lastSyncedBlock_logs_operators' + +/** + * Utility function to seed event logs + * + * @param fromBlock + * @param toBlock + */ +export async function seedLogsOperatorMetadata(toBlock?: bigint, fromBlock?: bigint) { + console.log('Seeding Event Logs for OperatorMetadataURIUpdated...') + + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + const viemClient = getViemClient() + const prismaClient = getPrismaClient() + + const logsOperatorMetadataURIUpdated: prisma.EventLogs_OperatorMetadataURIUpdated[] = [] + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + try { + const logs = await viemClient.getLogs({ + address: [ + getEigenContracts().DelegationManager + ], + events: [ + parseAbiItem( + 'event OperatorMetadataURIUpdated(address indexed operator, string metadataURI)' + ) + ], + fromBlock, + toBlock + }) + + // Setup a list containing event data + for (const l in logs) { + const log = logs[l] + + logsOperatorMetadataURIUpdated.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + operator: String(log.args.operator), + metadataURI: String(log.args.metadataURI) + }) + } + + dbTransactions.push( + prismaClient.eventLogs_OperatorMetadataURIUpdated.createMany({ + data: logsOperatorMetadataURIUpdated, + skipDuplicates: true + }) + ) + + // Store last synced block + dbTransactions.push( + prismaClient.settings.upsert({ + where: { key: blockSyncKeyLogs }, + update: { value: Number(toBlock) }, + create: { key: blockSyncKeyLogs, value: Number(toBlock) } + }) + ) + + // Update database + await bulkUpdateDbTransactions(dbTransactions) + } catch (error) {} + }) + + console.log( + `Seeded OperatorMetadataURIUpdated logs between blocks ${firstBlock} ${lastBlock}: ${logsOperatorMetadataURIUpdated.length}` + ) +} \ No newline at end of file diff --git a/packages/seeder/src/events/seedLogsOperatorShares.ts b/packages/seeder/src/events/seedLogsOperatorShares.ts new file mode 100644 index 00000000..dac18994 --- /dev/null +++ b/packages/seeder/src/events/seedLogsOperatorShares.ts @@ -0,0 +1,123 @@ +import prisma from '@prisma/client' +import { parseAbiItem } from 'viem' +import { getEigenContracts } from '../data/address' +import { getViemClient } from '../utils/viemClient' +import { + bulkUpdateDbTransactions, + fetchLastSyncBlock, + getBlockDataFromDb, + loopThroughBlocks +} from '../utils/seeder' +import { getPrismaClient } from '../utils/prismaClient' + +const blockSyncKeyLogs = 'lastSyncedBlock_logs_operatorShares' + +/** + * Utility function to seed event logs + * + * @param fromBlock + * @param toBlock + */ +export async function seedLogsOperatorShares(toBlock?: bigint, fromBlock?: bigint) { + console.log('Seeding Event Logs for OperatorSharesIncreased and OperatorSharesDecreased...') + + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + const viemClient = getViemClient() + const prismaClient = getPrismaClient() + + const logsOperatorSharesIncreased: prisma.EventLogs_OperatorSharesIncreased[] = [] + const logsOperatorSharesDecreased: prisma.EventLogs_OperatorSharesDecreased[] = [] + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + try { + const logs = await viemClient.getLogs({ + address: [ + getEigenContracts().DelegationManager + ], + events: [ + parseAbiItem( + 'event OperatorSharesIncreased(address indexed operator, address staker, address strategy, uint256 shares)' + ), + parseAbiItem( + 'event OperatorSharesDecreased(address indexed operator, address staker, address strategy, uint256 shares)' + ), + ], + fromBlock, + toBlock + }) + + // Setup a list containing event data + for (const l in logs) { + const log = logs[l] + + logsOperatorSharesIncreased.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + operator: String(log.args.operator), + staker: String(log.args.staker), + strategy: String(log.args.strategy), + shares: String(log.args.shares) + }) + + logsOperatorSharesDecreased.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + operator: String(log.args.operator), + staker: String(log.args.staker), + strategy: String(log.args.strategy), + shares: String(log.args.shares) + }) + } + + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesIncreased.createMany({ + data: logsOperatorSharesIncreased, + skipDuplicates: true + }) + ) + + dbTransactions.push( + prismaClient.eventLogs_OperatorSharesDecreased.createMany({ + data: logsOperatorSharesDecreased, + skipDuplicates: true + }) + ) + + // Store last synced block + dbTransactions.push( + prismaClient.settings.upsert({ + where: { key: blockSyncKeyLogs }, + update: { value: Number(toBlock) }, + create: { key: blockSyncKeyLogs, value: Number(toBlock) } + }) + ) + + // Update database + await bulkUpdateDbTransactions(dbTransactions) + } catch (error) {} + }) + + console.log( + `Seeded OperatorSharesIncreased logs between blocks ${firstBlock} ${lastBlock}: ${logsOperatorSharesIncreased.length}` + ) + console.log( + `Seeded OperatorSharesDecreased logs between blocks ${firstBlock} ${lastBlock}: ${logsOperatorSharesDecreased.length}` + ) +} \ No newline at end of file diff --git a/packages/seeder/src/events/seedLogsPodDeployed.ts b/packages/seeder/src/events/seedLogsPodDeployed.ts new file mode 100644 index 00000000..50e1aed2 --- /dev/null +++ b/packages/seeder/src/events/seedLogsPodDeployed.ts @@ -0,0 +1,94 @@ +import prisma from '@prisma/client' +import { parseAbiItem } from 'viem' +import { getEigenContracts } from '../data/address' +import { getViemClient } from '../utils/viemClient' +import { + bulkUpdateDbTransactions, + fetchLastSyncBlock, + getBlockDataFromDb, + loopThroughBlocks +} from '../utils/seeder' +import { getPrismaClient } from '../utils/prismaClient' + +const blockSyncKeyLogs = 'lastSyncedBlock_logs_pods' + +/** + * Utility function to seed event logs + * + * @param fromBlock + * @param toBlock + */ +export async function seedLogsPodDeployed(toBlock?: bigint, fromBlock?: bigint) { + console.log('Seeding Event Logs for PodDeployed...') + + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + const viemClient = getViemClient() + const prismaClient = getPrismaClient() + + const logsPodDeployed: prisma.EventLogs_PodDeployed[] = [] + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + try { + const logs = await viemClient.getLogs({ + address: [ + getEigenContracts().EigenPodManager + ], + events: [ + parseAbiItem( + 'event PodDeployed(address indexed eigenPod, address indexed podOwner)' + ) + ], + fromBlock, + toBlock + }) + + // Setup a list containing event data + for (const l in logs) { + const log = logs[l] + + logsPodDeployed.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + eigenPod: String(log.args.eigenPod), + podOwner: String(log.args.podOwner) + }) + } + + dbTransactions.push( + prismaClient.eventLogs_PodDeployed.createMany({ + data: logsPodDeployed, + skipDuplicates: true + }) + ) + + // Store last synced block + dbTransactions.push( + prismaClient.settings.upsert({ + where: { key: blockSyncKeyLogs }, + update: { value: Number(toBlock) }, + create: { key: blockSyncKeyLogs, value: Number(toBlock) } + }) + ) + + // Update database + await bulkUpdateDbTransactions(dbTransactions) + } catch (error) {} + }) + + console.log( + `Seeded PodDeployed logs between blocks ${firstBlock} ${lastBlock}: ${logsPodDeployed.length}` + ) +} \ No newline at end of file diff --git a/packages/seeder/src/events/seedLogsStakerDelegation.ts b/packages/seeder/src/events/seedLogsStakerDelegation.ts new file mode 100644 index 00000000..3f6a5344 --- /dev/null +++ b/packages/seeder/src/events/seedLogsStakerDelegation.ts @@ -0,0 +1,119 @@ +import prisma from '@prisma/client' +import { parseAbiItem } from 'viem' +import { getEigenContracts } from '../data/address' +import { getViemClient } from '../utils/viemClient' +import { + bulkUpdateDbTransactions, + fetchLastSyncBlock, + getBlockDataFromDb, + loopThroughBlocks +} from '../utils/seeder' +import { getPrismaClient } from '../utils/prismaClient' + +const blockSyncKeyLogs = 'lastSyncedBlock_logs_stakers' + +/** + * Utility function to seed event logs + * + * @param fromBlock + * @param toBlock + */ +export async function seedLogsStakerDelegation(toBlock?: bigint, fromBlock?: bigint) { + console.log('Seeding Event Logs for StakerDelegated and StakerUndelegated...') + + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + const viemClient = getViemClient() + const prismaClient = getPrismaClient() + + const logsStakerDelegated: prisma.EventLogs_StakerDelegated[] = [] + const logsStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + try { + const logs = await viemClient.getLogs({ + address: [ + getEigenContracts().DelegationManager + ], + events: [ + parseAbiItem( + 'event StakerDelegated(address indexed staker, address indexed operator)' + ), + parseAbiItem( + 'event StakerUndelegated(address indexed staker, address indexed operator)' + ), + ], + fromBlock, + toBlock + }) + + // Setup a list containing event data + for (const l in logs) { + const log = logs[l] + + logsStakerDelegated.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + staker: String(log.args.staker), + operator: String(log.args.operator) + }) + + logsStakerUndelegated.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + staker: String(log.args.staker), + operator: String(log.args.operator) + }) + } + + dbTransactions.push( + prismaClient.eventLogs_StakerDelegated.createMany({ + data: logsStakerDelegated, + skipDuplicates: true + }) + ) + + dbTransactions.push( + prismaClient.eventLogs_StakerUndelegated.createMany({ + data: logsStakerUndelegated, + skipDuplicates: true + }) + ) + + // Store last synced block + dbTransactions.push( + prismaClient.settings.upsert({ + where: { key: blockSyncKeyLogs }, + update: { value: Number(toBlock) }, + create: { key: blockSyncKeyLogs, value: Number(toBlock) } + }) + ) + + // Update database + await bulkUpdateDbTransactions(dbTransactions) + } catch (error) {} + }) + + console.log( + `Seeded StakerDelegated logs between blocks ${firstBlock} ${lastBlock}: ${logsStakerDelegated.length}` + ) + console.log( + `Seeded StakerUndelegated logs between blocks ${firstBlock} ${lastBlock}: ${logsStakerUndelegated.length}` + ) +} \ No newline at end of file diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 5bd73333..67f84e2b 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -6,13 +6,17 @@ import { seedOperators } from './seedOperators' import { seedPods } from './seedPods' import { seedStakers } from './seedStakers' import { getViemClient } from './utils/viemClient' -import { seedBlockData } from './events/seedBlockData' -import { seedEventLogs } from './events/seedEventLogs' +import { seedBlockData } from './blocks/seedBlockData' +import { seedLogsAVSMetadata } from './events/seedLogsAVSMetadata' +import { seedLogsOperatorMetadata } from './events/seedLogsOperatorMetadata' +import { seedLogsOperatorAVSRegistrationStatus } from './events/seedLogsOperatorAVSRegistrationStatus' +import { seedLogsOperatorShares } from './events/seedLogsOperatorShares' +import { seedLogsStakerDelegation } from './events/seedLogsStakerDelegation' +import { seedLogsPodDeployed } from './events/seedLogsPodDeployed' import { seedOperatorShares } from './seedOperatorShares' import { seedValidators } from './seedValidators' import { seedQueuedWithdrawals } from './seedWithdrawalsQueued' import { seedCompletedWithdrawals } from './seedWithdrawalsCompleted' -import { fetchLastLogBlock } from './utils/events' console.log('Initializing seeder ...') @@ -28,7 +32,12 @@ async function seedEventLogsLoop() { console.log('Seeding Block and Log Data ...', targetBlock) await seedBlockData(targetBlock) - await seedEventLogs(targetBlock) + await seedLogsAVSMetadata(targetBlock) + await seedLogsOperatorMetadata(targetBlock) + await seedLogsOperatorAVSRegistrationStatus(targetBlock) + await seedLogsOperatorShares(targetBlock) + await seedLogsStakerDelegation(targetBlock) + await seedLogsPodDeployed(targetBlock) } catch (error) { console.log('Failed to seed Block and Log Data at:', Date.now()) console.log(error) @@ -43,21 +52,18 @@ async function seedEigenDataLoop() { while (true) { try { - const targetBlock = await fetchLastLogBlock() - - if (targetBlock) { - console.log('Seeding Eigen Data ...', targetBlock) - - await seedAvs(targetBlock) - await seedOperators(targetBlock) - await seedAvsOperators(targetBlock) - await seedStakers(targetBlock) - await seedOperatorShares(targetBlock) - await seedQueuedWithdrawals(targetBlock) - await seedCompletedWithdrawals(targetBlock) - } + console.log('Seeding Eigen Data ...') + + await seedAvs() + await seedOperators() + await seedAvsOperators() + await seedStakers() + await seedOperatorShares() + await seedQueuedWithdrawals() + await seedCompletedWithdrawals() + } catch (error) { - console.log('Failed to seed AVS and Opeartors at:', Date.now()) + console.log('Failed to seed AVS and Operators at:', Date.now()) console.log(error) } @@ -70,16 +76,13 @@ async function seedEigenPodValidators() { while (true) { try { - const targetBlock = await fetchLastLogBlock() + console.log('Seeding Eigen Pods Data ...') - if (targetBlock) { - console.log('Seeding Eigen Pods Data ...', targetBlock) - - await seedPods(targetBlock) - await seedValidators() - } + await seedPods() + await seedValidators() } catch (error) { console.log('Failed to seed validators at block:', Date.now()) + console.log(error) } await delay(600) // Wait for 10 minutes (600 seconds) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 16c9d033..e0e1e9dd 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -2,7 +2,6 @@ import type prisma from '@prisma/client' import { isValidMetadataUrl, validateMetadata } from './utils/metadata' import { type EntityMetadata, defaultMetadata } from './utils/metadata' import { getPrismaClient } from './utils/prismaClient' -import { fetchLastLogBlock } from './utils/events' import { baseBlock, bulkUpdateDbTransactions, @@ -11,6 +10,7 @@ import { } from './utils/seeder' const blockSyncKey = 'lastSyncedBlock_avs' +const blockSyncKeyLogs = 'lastSyncedBlock_logs_avs' interface AvsEntryRecord { metadata: EntityMetadata @@ -27,15 +27,15 @@ interface AvsEntryRecord { * @param toBlock */ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding AVS ...') - const prismaClient = getPrismaClient() const avsList: Map = new Map() const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() + const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + + console.log(`Seeding AVS from ${firstBlock} - ${lastBlock}`) const logs = await prismaClient.eventLogs_AVSMetadataURIUpdated.findMany({ where: { @@ -55,6 +55,8 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const blockNumber = BigInt(log.blockNumber) const timestamp = log.blockTime + + /* Commented out for testing until merge with #75 try { if (log.metadataURI && isValidMetadataUrl(log.metadataURI)) { const response = await fetch(log.metadataURI) @@ -98,11 +100,33 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { updatedAt: timestamp }) } // Ignore case where Avs is already registered and is updated with invalid metadata uri + } */ + + // Seeding without metadata + if (existingRecord) { + // Avs already registered + avsList.set(avsAddress, { + metadata: defaultMetadata, + createdAtBlock: existingRecord.createdAtBlock, + updatedAtBlock: blockNumber, + createdAt: existingRecord.createdAt, + updatedAt: timestamp + }) + } else { + // Avs not registered + avsList.set(avsAddress, { + metadata: defaultMetadata, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) } } + console.log( `Avs registered between blocks ${firstBlock} ${lastBlock}: ${logs.length}` - ) + ) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedAvsOperators.ts b/packages/seeder/src/seedAvsOperators.ts index 7978cf20..57d33b22 100644 --- a/packages/seeder/src/seedAvsOperators.ts +++ b/packages/seeder/src/seedAvsOperators.ts @@ -1,4 +1,3 @@ -import { fetchLastLogBlock } from './utils/events' import { getPrismaClient } from './utils/prismaClient' import { baseBlock, @@ -8,17 +7,18 @@ import { } from './utils/seeder' const blockSyncKey = 'lastSyncedBlock_avsOperators' +const blockSyncKeyLogs = 'lastSyncedBlock_logs_avsOperators' export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding AVS Operators ...') - const prismaClient = getPrismaClient() const avsOperatorsList: Map> = new Map() const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() + const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + + console.log(`Seeding AVSOperators from ${firstBlock} - ${lastBlock}`) // Load initial operator staker state const avs = await prismaClient.avs.findMany({ diff --git a/packages/seeder/src/seedOperatorShares.ts b/packages/seeder/src/seedOperatorShares.ts index 422f52e6..4fea40a7 100644 --- a/packages/seeder/src/seedOperatorShares.ts +++ b/packages/seeder/src/seedOperatorShares.ts @@ -1,5 +1,4 @@ import { getPrismaClient } from './utils/prismaClient' -import { fetchLastLogBlock } from './utils/events' import { baseBlock, bulkUpdateDbTransactions, @@ -9,10 +8,9 @@ import { } from './utils/seeder' const blockSyncKey = 'lastSyncedBlock_operatorShares' +const blockSyncKeyLogs = 'lastSyncedBlock_logs_operatorShares' export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding operator shares ...') - const prismaClient = getPrismaClient() const operatorShares: IMap< string, @@ -22,7 +20,9 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() + const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + + console.log(`Seeding Operator Shares from ${firstBlock} - ${lastBlock}`) if (firstBlock === baseBlock) { await prismaClient.operatorStrategyShares.deleteMany() diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index a9c9d6ca..50694f6e 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -6,7 +6,6 @@ import { isValidMetadataUrl, validateMetadata } from './utils/metadata' -import { fetchLastLogBlock } from './utils/events' import { baseBlock, bulkUpdateDbTransactions, @@ -15,6 +14,7 @@ import { } from './utils/seeder' const blockSyncKey = 'lastSyncedBlock_operators' +const blockSyncKeyLogs = 'lastSyncedBlock_logs_operators' interface OperatorEntryRecord { metadata: EntityMetadata @@ -25,15 +25,15 @@ interface OperatorEntryRecord { } export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding Operators ...') - const prismaClient = getPrismaClient() const operatorList: Map = new Map() const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() + const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + + console.log(`Seeding Operators from ${firstBlock} - ${lastBlock}`) const logs = await prismaClient.eventLogs_OperatorMetadataURIUpdated.findMany( { @@ -55,6 +55,8 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const blockNumber = BigInt(log.blockNumber) const timestamp = log.blockTime + + /* Commented out for testing until merge with #75 try { if (log.metadataURI && isValidMetadataUrl(log.metadataURI)) { const response = await fetch(log.metadataURI) @@ -98,9 +100,29 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { updatedAt: timestamp }) } // Ignore case where Operator is already registered and is updated with invalid metadata uri + }*/ + + // Seeding without metadata + if (existingRecord) { + // Operator already registered + operatorList.set(operatorAddress, { + metadata: defaultMetadata, + createdAtBlock: existingRecord.createdAtBlock, + updatedAtBlock: blockNumber, + createdAt: existingRecord.createdAt, + updatedAt: timestamp + }) + } else { + // Operator not registered + operatorList.set(operatorAddress, { + metadata: defaultMetadata, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) } } - console.log( `Operators registered between blocks ${firstBlock} ${lastBlock}: ${logs.length}` ) @@ -180,7 +202,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { await bulkUpdateDbTransactions(dbTransactions) - // Storing last sycned block + // Storing last synced block await saveLastSyncBlock(blockSyncKey, lastBlock) console.log('Seeded operators:', operatorList.size) diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index e435bafd..6e400aa4 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -1,5 +1,4 @@ import type prisma from '@prisma/client' -import { fetchLastLogBlock } from './utils/events' import { getPrismaClient } from './utils/prismaClient' import { baseBlock, @@ -9,6 +8,7 @@ import { } from './utils/seeder' const blockSyncKey = 'lastSyncedBlock_pods' +const blockSyncKeyLogs = 'lastSyncedBlock_logs_pods' /** * @@ -16,15 +16,15 @@ const blockSyncKey = 'lastSyncedBlock_pods' * @param toBlock */ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding Pods ...') - const prismaClient = getPrismaClient() const podList: prisma.Pod[] = [] const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() + const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + + console.log(`Seeding Pods from ${firstBlock} - ${lastBlock}`) const logs = await prismaClient.eventLogs_PodDeployed.findMany({ where: { diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index 52b93130..06d5cfd5 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -1,5 +1,4 @@ import type prisma from '@prisma/client' -import { fetchLastLogBlock } from './utils/events' import { getPrismaClient } from './utils/prismaClient' import { type IMap, @@ -10,6 +9,7 @@ import { } from './utils/seeder' const blockSyncKey = 'lastSyncedBlock_stakers' +const blockSyncKeyLogs = 'lastSyncedBlock_logs_stakers' interface StakerEntryRecord { operatorAddress: string | null @@ -21,15 +21,15 @@ interface StakerEntryRecord { } export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding stakers ...') - const prismaClient = getPrismaClient() const stakers: IMap = new Map() const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastLogBlock() + const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + + console.log(`Seeding Stakers from ${firstBlock} - ${lastBlock}`) if (firstBlock === baseBlock) { await prismaClient.stakerStrategyShares.deleteMany() diff --git a/packages/seeder/src/utils/events.ts b/packages/seeder/src/utils/events.ts deleted file mode 100644 index 1c642f5c..00000000 --- a/packages/seeder/src/utils/events.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { getPrismaClient } from '../utils/prismaClient' - -// TBD -export interface TransactionLog { - address: string - transactionHash: string - transactionIndex: number - blockNumber: bigint - blockHash: string - blockTime: Date -} - -// TBD -export async function fetchLastLogBlock(): Promise { - const prismaClient = getPrismaClient() - - const lastSyncedBlockData = await prismaClient.settings.findUnique({ - where: { key: 'lastSyncedBlock_logs' } - }) - - return lastSyncedBlockData?.value - ? BigInt(lastSyncedBlockData.value as number) - : 0n -} From 9347d5c9e77b119d125252c27edfc67a4756caba Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:27:59 +0530 Subject: [PATCH 33/62] Revert disabling of test case metadata seeding --- packages/seeder/src/seedOperators.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index 50694f6e..430f9e59 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -31,7 +31,9 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock + ? toBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) console.log(`Seeding Operators from ${firstBlock} - ${lastBlock}`) @@ -55,8 +57,6 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const blockNumber = BigInt(log.blockNumber) const timestamp = log.blockTime - - /* Commented out for testing until merge with #75 try { if (log.metadataURI && isValidMetadataUrl(log.metadataURI)) { const response = await fetch(log.metadataURI) @@ -100,7 +100,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { updatedAt: timestamp }) } // Ignore case where Operator is already registered and is updated with invalid metadata uri - }*/ + } // Seeding without metadata if (existingRecord) { From 89899284806ef30427c2862a45c42dc0598d3bef Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:28:37 +0530 Subject: [PATCH 34/62] Fix for cummulative bulk db transaction data overload --- packages/seeder/src/blocks/seedBlockData.ts | 27 ++++--- .../seeder/src/events/seedLogsAVSMetadata.ts | 50 ++++++------ .../seedLogsOperatorAVSRegistrationStatus.ts | 47 ++++++----- .../src/events/seedLogsOperatorMetadata.ts | 50 ++++++------ .../src/events/seedLogsOperatorShares.ts | 79 ++++++++++--------- .../seeder/src/events/seedLogsPodDeployed.ts | 52 ++++++------ .../src/events/seedLogsStakerDelegation.ts | 70 ++++++++-------- packages/seeder/src/index.ts | 3 +- packages/seeder/src/utils/seeder.ts | 17 ++-- 9 files changed, 212 insertions(+), 183 deletions(-) diff --git a/packages/seeder/src/blocks/seedBlockData.ts b/packages/seeder/src/blocks/seedBlockData.ts index a19d6a01..52c52f82 100644 --- a/packages/seeder/src/blocks/seedBlockData.ts +++ b/packages/seeder/src/blocks/seedBlockData.ts @@ -1,11 +1,13 @@ import prisma from '@prisma/client' import { getPrismaClient } from '../utils/prismaClient' import { getViemClient } from '../utils/viemClient' -import { baseBlock, loopThroughBlocks } from '../utils/seeder' +import { + baseBlock, + bulkUpdateDbTransactions, + loopThroughBlocks +} from '../utils/seeder' export async function seedBlockData(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding Block Data ...') - const viemClient = getViemClient() const prismaClient = getPrismaClient() @@ -44,15 +46,18 @@ export async function seedBlockData(toBlock?: bigint, fromBlock?: bigint) { }) } - await prismaClient.evm_BlockData.createMany({ - data: newBlockData, - skipDuplicates: true - }) - - console.log(`Retrieved Block Data for ${fromBlock} - ${toBlock}`) + await bulkUpdateDbTransactions( + [ + prismaClient.evm_BlockData.createMany({ + data: newBlockData, + skipDuplicates: true + }) + ], + `Block data from: ${fromBlock} to: ${toBlock} size: ${Number( + toBlock - fromBlock + )}` + ) }, 99n ) - - console.log('Seeded Block Data:', Number(lastBlock - firstBlock)) } diff --git a/packages/seeder/src/events/seedLogsAVSMetadata.ts b/packages/seeder/src/events/seedLogsAVSMetadata.ts index da5ae916..7f056d85 100644 --- a/packages/seeder/src/events/seedLogsAVSMetadata.ts +++ b/packages/seeder/src/events/seedLogsAVSMetadata.ts @@ -18,30 +18,31 @@ const blockSyncKeyLogs = 'lastSyncedBlock_logs_avs' * @param fromBlock * @param toBlock */ -export async function seedLogsAVSMetadata(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding Event Logs for AVSMetadataURIUpdated...') - - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] - +export async function seedLogsAVSMetadata( + toBlock?: bigint, + fromBlock?: bigint +) { const viemClient = getViemClient() const prismaClient = getPrismaClient() - const logsAVSMetadataURIUpdated: prisma.EventLogs_AVSMetadataURIUpdated[] = [] - const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + let totalSeeded = 0 + // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + const logsAVSMetadataURIUpdated: prisma.EventLogs_AVSMetadataURIUpdated[] = + [] + const logs = await viemClient.getLogs({ - address: [ - getEigenContracts().AVSDirectory - ], + address: [getEigenContracts().AVSDirectory], events: [ parseAbiItem( 'event AVSMetadataURIUpdated(address indexed avs, string metadataURI)' @@ -55,17 +56,17 @@ export async function seedLogsAVSMetadata(toBlock?: bigint, fromBlock?: bigint) for (const l in logs) { const log = logs[l] - logsAVSMetadataURIUpdated.push({ - address: log.address, + logsAVSMetadataURIUpdated.push({ + address: log.address, transactionHash: log.transactionHash, transactionIndex: log.transactionIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), - avs: String(log.args.avs), - metadataURI: String(log.args.metadataURI) - }) - } + avs: String(log.args.avs), + metadataURI: String(log.args.metadataURI) + }) + } dbTransactions.push( prismaClient.eventLogs_AVSMetadataURIUpdated.createMany({ @@ -84,11 +85,14 @@ export async function seedLogsAVSMetadata(toBlock?: bigint, fromBlock?: bigint) ) // Update database - await bulkUpdateDbTransactions(dbTransactions) + const seedLength = logsAVSMetadataURIUpdated.length + + await bulkUpdateDbTransactions( + dbTransactions, + `AVS Metadata from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + ) + + totalSeeded += seedLength } catch (error) {} }) - - console.log( - `Seeded AVSMetadataURIUpdated logs between blocks ${firstBlock} ${lastBlock}: ${logsAVSMetadataURIUpdated.length}` - ) -} \ No newline at end of file +} diff --git a/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts b/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts index f81ebc13..96c1c73a 100644 --- a/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts +++ b/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts @@ -18,30 +18,32 @@ const blockSyncKeyLogs = 'lastSyncedBlock_logs_avsOperators' * @param fromBlock * @param toBlock */ -export async function seedLogsOperatorAVSRegistrationStatus(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding Event Logs for OperatorAVSRegistrationStatusUpdated...') - - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] - +export async function seedLogsOperatorAVSRegistrationStatus( + toBlock?: bigint, + fromBlock?: bigint +) { const viemClient = getViemClient() const prismaClient = getPrismaClient() - const logsOperatorAVSRegistrationStatusUpdated: prisma.EventLogs_OperatorAVSRegistrationStatusUpdated[] = [] - const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + let totalSeeded = 0 + // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + const logsOperatorAVSRegistrationStatusUpdated: prisma.EventLogs_OperatorAVSRegistrationStatusUpdated[] = + [] + const logs = await viemClient.getLogs({ - address: [ - getEigenContracts().AVSDirectory - ], + address: [getEigenContracts().AVSDirectory], events: [ parseAbiItem( 'event OperatorAVSRegistrationStatusUpdated(address indexed operator, address indexed avs, uint8 status)' @@ -55,8 +57,8 @@ export async function seedLogsOperatorAVSRegistrationStatus(toBlock?: bigint, fr for (const l in logs) { const log = logs[l] - logsOperatorAVSRegistrationStatusUpdated.push({ - address: log.address, + logsOperatorAVSRegistrationStatusUpdated.push({ + address: log.address, transactionHash: log.transactionHash, transactionIndex: log.transactionIndex, blockNumber: BigInt(log.blockNumber), @@ -65,8 +67,8 @@ export async function seedLogsOperatorAVSRegistrationStatus(toBlock?: bigint, fr operator: String(log.args.operator), avs: String(log.args.avs), status: Number(log.args.status) - }) - } + }) + } dbTransactions.push( prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.createMany({ @@ -85,11 +87,14 @@ export async function seedLogsOperatorAVSRegistrationStatus(toBlock?: bigint, fr ) // Update database - await bulkUpdateDbTransactions(dbTransactions) + const seedLength = logsOperatorAVSRegistrationStatusUpdated.length + + await bulkUpdateDbTransactions( + dbTransactions, + `Operator Registration from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + ) + + totalSeeded += seedLength } catch (error) {} }) - - console.log( - `Seeded OperatorAVSRegistrationStatusUpdated logs between blocks ${firstBlock} ${lastBlock}: ${logsOperatorAVSRegistrationStatusUpdated.length}` - ) -} \ No newline at end of file +} diff --git a/packages/seeder/src/events/seedLogsOperatorMetadata.ts b/packages/seeder/src/events/seedLogsOperatorMetadata.ts index e31db3cd..4a2f3d1c 100644 --- a/packages/seeder/src/events/seedLogsOperatorMetadata.ts +++ b/packages/seeder/src/events/seedLogsOperatorMetadata.ts @@ -18,30 +18,31 @@ const blockSyncKeyLogs = 'lastSyncedBlock_logs_operators' * @param fromBlock * @param toBlock */ -export async function seedLogsOperatorMetadata(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding Event Logs for OperatorMetadataURIUpdated...') - - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] - +export async function seedLogsOperatorMetadata( + toBlock?: bigint, + fromBlock?: bigint +) { const viemClient = getViemClient() const prismaClient = getPrismaClient() - const logsOperatorMetadataURIUpdated: prisma.EventLogs_OperatorMetadataURIUpdated[] = [] - const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + let totalSeeded = 0 + // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + const logsOperatorMetadataURIUpdated: prisma.EventLogs_OperatorMetadataURIUpdated[] = + [] + const logs = await viemClient.getLogs({ - address: [ - getEigenContracts().DelegationManager - ], + address: [getEigenContracts().DelegationManager], events: [ parseAbiItem( 'event OperatorMetadataURIUpdated(address indexed operator, string metadataURI)' @@ -55,17 +56,17 @@ export async function seedLogsOperatorMetadata(toBlock?: bigint, fromBlock?: big for (const l in logs) { const log = logs[l] - logsOperatorMetadataURIUpdated.push({ - address: log.address, + logsOperatorMetadataURIUpdated.push({ + address: log.address, transactionHash: log.transactionHash, transactionIndex: log.transactionIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), - operator: String(log.args.operator), - metadataURI: String(log.args.metadataURI) - }) - } + operator: String(log.args.operator), + metadataURI: String(log.args.metadataURI) + }) + } dbTransactions.push( prismaClient.eventLogs_OperatorMetadataURIUpdated.createMany({ @@ -84,11 +85,14 @@ export async function seedLogsOperatorMetadata(toBlock?: bigint, fromBlock?: big ) // Update database - await bulkUpdateDbTransactions(dbTransactions) + const seedLength = logsOperatorMetadataURIUpdated.length + + await bulkUpdateDbTransactions( + dbTransactions, + `Operator Metadata from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + ) + + totalSeeded += seedLength } catch (error) {} }) - - console.log( - `Seeded OperatorMetadataURIUpdated logs between blocks ${firstBlock} ${lastBlock}: ${logsOperatorMetadataURIUpdated.length}` - ) -} \ No newline at end of file +} diff --git a/packages/seeder/src/events/seedLogsOperatorShares.ts b/packages/seeder/src/events/seedLogsOperatorShares.ts index dac18994..0f58ea6b 100644 --- a/packages/seeder/src/events/seedLogsOperatorShares.ts +++ b/packages/seeder/src/events/seedLogsOperatorShares.ts @@ -18,38 +18,40 @@ const blockSyncKeyLogs = 'lastSyncedBlock_logs_operatorShares' * @param fromBlock * @param toBlock */ -export async function seedLogsOperatorShares(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding Event Logs for OperatorSharesIncreased and OperatorSharesDecreased...') - - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] - +export async function seedLogsOperatorShares( + toBlock?: bigint, + fromBlock?: bigint +) { const viemClient = getViemClient() const prismaClient = getPrismaClient() - const logsOperatorSharesIncreased: prisma.EventLogs_OperatorSharesIncreased[] = [] - const logsOperatorSharesDecreased: prisma.EventLogs_OperatorSharesDecreased[] = [] - const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + let totalSeeded = 0 + // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + const logsOperatorSharesIncreased: prisma.EventLogs_OperatorSharesIncreased[] = + [] + const logsOperatorSharesDecreased: prisma.EventLogs_OperatorSharesDecreased[] = + [] + const logs = await viemClient.getLogs({ - address: [ - getEigenContracts().DelegationManager - ], + address: [getEigenContracts().DelegationManager], events: [ parseAbiItem( 'event OperatorSharesIncreased(address indexed operator, address staker, address strategy, uint256 shares)' ), parseAbiItem( 'event OperatorSharesDecreased(address indexed operator, address staker, address strategy, uint256 shares)' - ), + ) ], fromBlock, toBlock @@ -59,32 +61,32 @@ export async function seedLogsOperatorShares(toBlock?: bigint, fromBlock?: bigin for (const l in logs) { const log = logs[l] - logsOperatorSharesIncreased.push({ - address: log.address, + logsOperatorSharesIncreased.push({ + address: log.address, transactionHash: log.transactionHash, transactionIndex: log.transactionIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), - operator: String(log.args.operator), - staker: String(log.args.staker), - strategy: String(log.args.strategy), - shares: String(log.args.shares) - }) + operator: String(log.args.operator), + staker: String(log.args.staker), + strategy: String(log.args.strategy), + shares: String(log.args.shares) + }) - logsOperatorSharesDecreased.push({ - address: log.address, + logsOperatorSharesDecreased.push({ + address: log.address, transactionHash: log.transactionHash, transactionIndex: log.transactionIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), - operator: String(log.args.operator), - staker: String(log.args.staker), - strategy: String(log.args.strategy), - shares: String(log.args.shares) - }) - } + operator: String(log.args.operator), + staker: String(log.args.staker), + strategy: String(log.args.strategy), + shares: String(log.args.shares) + }) + } dbTransactions.push( prismaClient.eventLogs_OperatorSharesIncreased.createMany({ @@ -93,7 +95,7 @@ export async function seedLogsOperatorShares(toBlock?: bigint, fromBlock?: bigin }) ) - dbTransactions.push( + dbTransactions.push( prismaClient.eventLogs_OperatorSharesDecreased.createMany({ data: logsOperatorSharesDecreased, skipDuplicates: true @@ -110,14 +112,15 @@ export async function seedLogsOperatorShares(toBlock?: bigint, fromBlock?: bigin ) // Update database - await bulkUpdateDbTransactions(dbTransactions) + const seedLength = + logsOperatorSharesDecreased.length + logsOperatorSharesIncreased.length + + await bulkUpdateDbTransactions( + dbTransactions, + `Operator Shares from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + ) + + totalSeeded += seedLength } catch (error) {} }) - - console.log( - `Seeded OperatorSharesIncreased logs between blocks ${firstBlock} ${lastBlock}: ${logsOperatorSharesIncreased.length}` - ) - console.log( - `Seeded OperatorSharesDecreased logs between blocks ${firstBlock} ${lastBlock}: ${logsOperatorSharesDecreased.length}` - ) -} \ No newline at end of file +} diff --git a/packages/seeder/src/events/seedLogsPodDeployed.ts b/packages/seeder/src/events/seedLogsPodDeployed.ts index 50e1aed2..7d3cc23c 100644 --- a/packages/seeder/src/events/seedLogsPodDeployed.ts +++ b/packages/seeder/src/events/seedLogsPodDeployed.ts @@ -18,30 +18,31 @@ const blockSyncKeyLogs = 'lastSyncedBlock_logs_pods' * @param fromBlock * @param toBlock */ -export async function seedLogsPodDeployed(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding Event Logs for PodDeployed...') - - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] - +export async function seedLogsPodDeployed( + toBlock?: bigint, + fromBlock?: bigint +) { const viemClient = getViemClient() const prismaClient = getPrismaClient() - const logsPodDeployed: prisma.EventLogs_PodDeployed[] = [] - const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + let totalSeeded = 0 + // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + const logsPodDeployed: prisma.EventLogs_PodDeployed[] = [] + const logs = await viemClient.getLogs({ - address: [ - getEigenContracts().EigenPodManager - ], + address: [getEigenContracts().EigenPodManager], events: [ parseAbiItem( 'event PodDeployed(address indexed eigenPod, address indexed podOwner)' @@ -55,17 +56,17 @@ export async function seedLogsPodDeployed(toBlock?: bigint, fromBlock?: bigint) for (const l in logs) { const log = logs[l] - logsPodDeployed.push({ - address: log.address, + logsPodDeployed.push({ + address: log.address, transactionHash: log.transactionHash, transactionIndex: log.transactionIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), - eigenPod: String(log.args.eigenPod), - podOwner: String(log.args.podOwner) - }) - } + eigenPod: String(log.args.eigenPod), + podOwner: String(log.args.podOwner) + }) + } dbTransactions.push( prismaClient.eventLogs_PodDeployed.createMany({ @@ -82,13 +83,16 @@ export async function seedLogsPodDeployed(toBlock?: bigint, fromBlock?: bigint) create: { key: blockSyncKeyLogs, value: Number(toBlock) } }) ) - + // Update database - await bulkUpdateDbTransactions(dbTransactions) + const seedLength = logsPodDeployed.length + + await bulkUpdateDbTransactions( + dbTransactions, + `Pod Deployed from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + ) + + totalSeeded += seedLength } catch (error) {} }) - - console.log( - `Seeded PodDeployed logs between blocks ${firstBlock} ${lastBlock}: ${logsPodDeployed.length}` - ) -} \ No newline at end of file +} diff --git a/packages/seeder/src/events/seedLogsStakerDelegation.ts b/packages/seeder/src/events/seedLogsStakerDelegation.ts index 3f6a5344..9c3adf13 100644 --- a/packages/seeder/src/events/seedLogsStakerDelegation.ts +++ b/packages/seeder/src/events/seedLogsStakerDelegation.ts @@ -18,38 +18,39 @@ const blockSyncKeyLogs = 'lastSyncedBlock_logs_stakers' * @param fromBlock * @param toBlock */ -export async function seedLogsStakerDelegation(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding Event Logs for StakerDelegated and StakerUndelegated...') - - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] - +export async function seedLogsStakerDelegation( + toBlock?: bigint, + fromBlock?: bigint +) { const viemClient = getViemClient() const prismaClient = getPrismaClient() - const logsStakerDelegated: prisma.EventLogs_StakerDelegated[] = [] - const logsStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] - const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + let totalSeeded = 0 + // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + const logsStakerDelegated: prisma.EventLogs_StakerDelegated[] = [] + const logsStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] + const logs = await viemClient.getLogs({ - address: [ - getEigenContracts().DelegationManager - ], + address: [getEigenContracts().DelegationManager], events: [ parseAbiItem( 'event StakerDelegated(address indexed staker, address indexed operator)' ), parseAbiItem( 'event StakerUndelegated(address indexed staker, address indexed operator)' - ), + ) ], fromBlock, toBlock @@ -59,28 +60,28 @@ export async function seedLogsStakerDelegation(toBlock?: bigint, fromBlock?: big for (const l in logs) { const log = logs[l] - logsStakerDelegated.push({ - address: log.address, + logsStakerDelegated.push({ + address: log.address, transactionHash: log.transactionHash, transactionIndex: log.transactionIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), - staker: String(log.args.staker), - operator: String(log.args.operator) - }) + staker: String(log.args.staker), + operator: String(log.args.operator) + }) - logsStakerUndelegated.push({ - address: log.address, + logsStakerUndelegated.push({ + address: log.address, transactionHash: log.transactionHash, transactionIndex: log.transactionIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), - staker: String(log.args.staker), - operator: String(log.args.operator) - }) - } + staker: String(log.args.staker), + operator: String(log.args.operator) + }) + } dbTransactions.push( prismaClient.eventLogs_StakerDelegated.createMany({ @@ -89,7 +90,7 @@ export async function seedLogsStakerDelegation(toBlock?: bigint, fromBlock?: big }) ) - dbTransactions.push( + dbTransactions.push( prismaClient.eventLogs_StakerUndelegated.createMany({ data: logsStakerUndelegated, skipDuplicates: true @@ -106,14 +107,15 @@ export async function seedLogsStakerDelegation(toBlock?: bigint, fromBlock?: big ) // Update database - await bulkUpdateDbTransactions(dbTransactions) + const seedLength = + logsStakerDelegated.length + logsStakerUndelegated.length + + await bulkUpdateDbTransactions( + dbTransactions, + `Staker Delegation from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + ) + + totalSeeded += seedLength } catch (error) {} }) - - console.log( - `Seeded StakerDelegated logs between blocks ${firstBlock} ${lastBlock}: ${logsStakerDelegated.length}` - ) - console.log( - `Seeded StakerUndelegated logs between blocks ${firstBlock} ${lastBlock}: ${logsStakerUndelegated.length}` - ) -} \ No newline at end of file +} diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 67f84e2b..3876088d 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -43,7 +43,7 @@ async function seedEventLogsLoop() { console.log(error) } - await delay(60) + await delay(30) } } @@ -61,7 +61,6 @@ async function seedEigenDataLoop() { await seedOperatorShares() await seedQueuedWithdrawals() await seedCompletedWithdrawals() - } catch (error) { console.log('Failed to seed AVS and Operators at:', Date.now()) console.log(error) diff --git a/packages/seeder/src/utils/seeder.ts b/packages/seeder/src/utils/seeder.ts index 77f3cfa1..0d128069 100644 --- a/packages/seeder/src/utils/seeder.ts +++ b/packages/seeder/src/utils/seeder.ts @@ -16,7 +16,7 @@ export async function loopThroughBlocks( firstBlock: bigint, lastBlock: bigint, cb: (fromBlock: bigint, toBlock: bigint) => Promise, - defaultBatchSize?: bigint, + defaultBatchSize?: bigint ) { const batchSize = defaultBatchSize ? defaultBatchSize : 9999n let currentBlock = firstBlock @@ -34,21 +34,24 @@ export async function loopThroughBlocks( return lastBlock } -// biome-ignore lint/suspicious/noExplicitAny: -export async function bulkUpdateDbTransactions(dbTransactions: any[]) { +export async function bulkUpdateDbTransactions( + // biome-ignore lint/suspicious/noExplicitAny: + dbTransactions: any[], + label?: string +) { const prismaClient = getPrismaClient() const chunkSize = 1000 let i = 0 - console.log('Updating db transactions', dbTransactions.length) + console.time(`[DB Write (${dbTransactions.length})] ${label || ''}`) for (const chunk of chunkArray(dbTransactions, chunkSize)) { - console.time(`Updating db transactions ${i}, size: ${chunk.length}`) await prismaClient.$transaction(chunk) - console.timeEnd(`Updating db transactions ${i}, size: ${chunk.length}`) i++ } + + console.timeEnd(`[DB Write (${dbTransactions.length})] ${label || ''}`) } export async function fetchLastSyncBlock(key: string): Promise { @@ -93,4 +96,4 @@ export async function getBlockDataFromDb(fromBlock: bigint, toBlock: bigint) { }) return new Map(blockData.map((block) => [block.number, block.timestamp])) -} \ No newline at end of file +} From 7c8aad1085e3ff677e18d2221ad46261c72f9aeb Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:38:28 +0530 Subject: [PATCH 35/62] Revert disabling of test case metadata seeding --- packages/seeder/src/seedAvs.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index e0e1e9dd..1d313674 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -33,7 +33,9 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock + ? toBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) console.log(`Seeding AVS from ${firstBlock} - ${lastBlock}`) @@ -55,8 +57,6 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const blockNumber = BigInt(log.blockNumber) const timestamp = log.blockTime - - /* Commented out for testing until merge with #75 try { if (log.metadataURI && isValidMetadataUrl(log.metadataURI)) { const response = await fetch(log.metadataURI) @@ -100,7 +100,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { updatedAt: timestamp }) } // Ignore case where Avs is already registered and is updated with invalid metadata uri - } */ + } // Seeding without metadata if (existingRecord) { @@ -126,7 +126,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { console.log( `Avs registered between blocks ${firstBlock} ${lastBlock}: ${logs.length}` - ) + ) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: From c2445be1ec583fc3f328f5b738376e1aebc76472 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Thu, 6 Jun 2024 20:23:30 +0530 Subject: [PATCH 36/62] changed filter to prevent double counting --- packages/seeder/src/seedAvs.ts | 23 +--------------------- packages/seeder/src/seedAvsOperators.ts | 2 +- packages/seeder/src/seedOperatorShares.ts | 2 +- packages/seeder/src/seedOperators.ts | 24 ++--------------------- packages/seeder/src/seedPods.ts | 2 +- packages/seeder/src/seedStakers.ts | 2 +- 6 files changed, 7 insertions(+), 48 deletions(-) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 1d313674..7498575a 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -42,7 +42,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const logs = await prismaClient.eventLogs_AVSMetadataURIUpdated.findMany({ where: { blockNumber: { - gte: firstBlock, + gt: firstBlock, lte: lastBlock } } @@ -101,27 +101,6 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { }) } // Ignore case where Avs is already registered and is updated with invalid metadata uri } - - // Seeding without metadata - if (existingRecord) { - // Avs already registered - avsList.set(avsAddress, { - metadata: defaultMetadata, - createdAtBlock: existingRecord.createdAtBlock, - updatedAtBlock: blockNumber, - createdAt: existingRecord.createdAt, - updatedAt: timestamp - }) - } else { - // Avs not registered - avsList.set(avsAddress, { - metadata: defaultMetadata, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } } console.log( diff --git a/packages/seeder/src/seedAvsOperators.ts b/packages/seeder/src/seedAvsOperators.ts index 57d33b22..1bb68581 100644 --- a/packages/seeder/src/seedAvsOperators.ts +++ b/packages/seeder/src/seedAvsOperators.ts @@ -31,7 +31,7 @@ export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { await prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.findMany({ where: { blockNumber: { - gte: firstBlock, + gt: firstBlock, lte: lastBlock } } diff --git a/packages/seeder/src/seedOperatorShares.ts b/packages/seeder/src/seedOperatorShares.ts index 4fea40a7..39d97c24 100644 --- a/packages/seeder/src/seedOperatorShares.ts +++ b/packages/seeder/src/seedOperatorShares.ts @@ -33,7 +33,7 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: firstBlock, + gt: firstBlock, lte: lastBlock } } diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index 430f9e59..9bb05728 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -41,7 +41,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { { where: { blockNumber: { - gte: firstBlock, + gt: firstBlock, lte: lastBlock } } @@ -101,28 +101,8 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { }) } // Ignore case where Operator is already registered and is updated with invalid metadata uri } - - // Seeding without metadata - if (existingRecord) { - // Operator already registered - operatorList.set(operatorAddress, { - metadata: defaultMetadata, - createdAtBlock: existingRecord.createdAtBlock, - updatedAtBlock: blockNumber, - createdAt: existingRecord.createdAt, - updatedAt: timestamp - }) - } else { - // Operator not registered - operatorList.set(operatorAddress, { - metadata: defaultMetadata, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } } + console.log( `Operators registered between blocks ${firstBlock} ${lastBlock}: ${logs.length}` ) diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index 6e400aa4..a38d85d6 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -29,7 +29,7 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { const logs = await prismaClient.eventLogs_PodDeployed.findMany({ where: { blockNumber: { - gte: firstBlock, + gt: firstBlock, lte: lastBlock } } diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index 06d5cfd5..5cb5e35f 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -39,7 +39,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: firstBlock, + gt: firstBlock, lte: lastBlock } } From 792cda717e35f237822921a28eb0eaa2b3f63c8e Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Fri, 7 Jun 2024 03:08:37 +0530 Subject: [PATCH 37/62] Bail early if there are no blocks to sync --- packages/seeder/src/seedAvs.ts | 6 ++++ packages/seeder/src/seedAvsOperators.ts | 10 +++++- packages/seeder/src/seedOperatorShares.ts | 10 +++++- packages/seeder/src/seedOperators.ts | 8 ++++- packages/seeder/src/seedPods.ts | 10 +++++- packages/seeder/src/seedStakers.ts | 38 ++++++++++++++++++++--- packages/seeder/src/utils/seeder.ts | 4 +-- 7 files changed, 75 insertions(+), 11 deletions(-) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 7498575a..b8faff90 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -37,6 +37,12 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + // Bail early if there is no block diff to sync + if (lastBlock - firstBlock <= 0) { + console.log(`AVS in sync ${firstBlock} - ${lastBlock}`) + return + } + console.log(`Seeding AVS from ${firstBlock} - ${lastBlock}`) const logs = await prismaClient.eventLogs_AVSMetadataURIUpdated.findMany({ diff --git a/packages/seeder/src/seedAvsOperators.ts b/packages/seeder/src/seedAvsOperators.ts index 1bb68581..ac6b5f17 100644 --- a/packages/seeder/src/seedAvsOperators.ts +++ b/packages/seeder/src/seedAvsOperators.ts @@ -16,7 +16,15 @@ export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock + ? toBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + + // Bail early if there is no block diff to sync + if (lastBlock - firstBlock <= 0) { + console.log(`AVSOperators in sync ${firstBlock} - ${lastBlock}`) + return + } console.log(`Seeding AVSOperators from ${firstBlock} - ${lastBlock}`) diff --git a/packages/seeder/src/seedOperatorShares.ts b/packages/seeder/src/seedOperatorShares.ts index 39d97c24..7042b83e 100644 --- a/packages/seeder/src/seedOperatorShares.ts +++ b/packages/seeder/src/seedOperatorShares.ts @@ -20,7 +20,15 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock + ? toBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + + // Bail early if there is no block diff to sync + if (lastBlock - firstBlock <= 0) { + console.log(`Operator Shares in sync ${firstBlock} - ${lastBlock}`) + return + } console.log(`Seeding Operator Shares from ${firstBlock} - ${lastBlock}`) diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index 9bb05728..6731675b 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -35,6 +35,12 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + // Bail early if there is no block diff to sync + if (lastBlock - firstBlock <= 0) { + console.log(`Operators in sync ${firstBlock} - ${lastBlock}`) + return + } + console.log(`Seeding Operators from ${firstBlock} - ${lastBlock}`) const logs = await prismaClient.eventLogs_OperatorMetadataURIUpdated.findMany( @@ -102,7 +108,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { } // Ignore case where Operator is already registered and is updated with invalid metadata uri } } - + console.log( `Operators registered between blocks ${firstBlock} ${lastBlock}: ${logs.length}` ) diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index a38d85d6..d63d20ac 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -22,7 +22,15 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock + ? toBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + + // Bail early if there is no block diff to sync + if (lastBlock - firstBlock <= 0) { + console.log(`Pods in sync ${firstBlock} - ${lastBlock}`) + return + } console.log(`Seeding Pods from ${firstBlock} - ${lastBlock}`) diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index 5cb5e35f..bc0e042f 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -27,7 +27,15 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock + ? toBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + + // Bail early if there is no block diff to sync + if (lastBlock - firstBlock <= 0) { + console.log(`Stakers in sync ${firstBlock} - ${lastBlock}`) + return + } console.log(`Seeding Stakers from ${firstBlock} - ${lastBlock}`) @@ -45,7 +53,12 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } }) .then((logs) => - logs.map((log) => ({ ...log, shares: '', strategy: '', eventName: 'StakerDelegated' })) + logs.map((log) => ({ + ...log, + shares: '', + strategy: '', + eventName: 'StakerDelegated' + })) ) const logsStakerUndelegated = await prismaClient.eventLogs_StakerUndelegated @@ -58,7 +71,12 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } }) .then((logs) => - logs.map((log) => ({ ...log, shares: '', strategy: '', eventName: 'StakerUndelegated' })) + logs.map((log) => ({ + ...log, + shares: '', + strategy: '', + eventName: 'StakerUndelegated' + })) ) const logsOperatorSharesIncreased = @@ -72,7 +90,12 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } }) .then((logs) => - logs.map((log) => ({ ...log, shares: log.shares, strategy: log.strategy, eventName: 'OperatorSharesIncreased' })) + logs.map((log) => ({ + ...log, + shares: log.shares, + strategy: log.strategy, + eventName: 'OperatorSharesIncreased' + })) ) const logsOperatorSharesDecreased = @@ -86,7 +109,12 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } }) .then((logs) => - logs.map((log) => ({ ...log, shares: log.shares, strategy: log.strategy, eventName: 'OperatorSharesDecreased' })) + logs.map((log) => ({ + ...log, + shares: log.shares, + strategy: log.strategy, + eventName: 'OperatorSharesDecreased' + })) ) const logs = [ diff --git a/packages/seeder/src/utils/seeder.ts b/packages/seeder/src/utils/seeder.ts index 0d128069..7c5ce0bd 100644 --- a/packages/seeder/src/utils/seeder.ts +++ b/packages/seeder/src/utils/seeder.ts @@ -18,7 +18,7 @@ export async function loopThroughBlocks( cb: (fromBlock: bigint, toBlock: bigint) => Promise, defaultBatchSize?: bigint ) { - const batchSize = defaultBatchSize ? defaultBatchSize : 9999n + const batchSize = defaultBatchSize ? defaultBatchSize : 4999n let currentBlock = firstBlock let nextBlock = firstBlock @@ -62,7 +62,7 @@ export async function fetchLastSyncBlock(key: string): Promise { }) return lastSyncedBlockData?.value - ? BigInt(lastSyncedBlockData.value as number) + 1n + ? BigInt(lastSyncedBlockData.value as number) : baseBlock } From bd71f940dc4cff2334626ef5b1d5ad2d7a929d5f Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Fri, 7 Jun 2024 03:35:37 +0530 Subject: [PATCH 38/62] Updated seeder logic for withdrawals --- .../migration.sql | 22 +++ .../migration.sql | 15 ++ packages/prisma/schema.prisma | 39 +++++- .../src/events/seedLogsWithdrawalCompleted.ts | 95 +++++++++++++ .../src/events/seedLogsWithdrawalQueued.ts | 103 ++++++++++++++ packages/seeder/src/index.ts | 30 ++-- .../seeder/src/seedWithdrawalsCompleted.ts | 55 ++++---- packages/seeder/src/seedWithdrawalsQueued.ts | 128 ++++++++---------- 8 files changed, 365 insertions(+), 122 deletions(-) create mode 100644 packages/prisma/migrations/20240606213654_include_raw_evm_logs_data_withdrawal/migration.sql create mode 100644 packages/prisma/migrations/20240606215914_include_raw_evm_logs_data_withdrawal_completed/migration.sql create mode 100644 packages/seeder/src/events/seedLogsWithdrawalCompleted.ts create mode 100644 packages/seeder/src/events/seedLogsWithdrawalQueued.ts diff --git a/packages/prisma/migrations/20240606213654_include_raw_evm_logs_data_withdrawal/migration.sql b/packages/prisma/migrations/20240606213654_include_raw_evm_logs_data_withdrawal/migration.sql new file mode 100644 index 00000000..143c6afa --- /dev/null +++ b/packages/prisma/migrations/20240606213654_include_raw_evm_logs_data_withdrawal/migration.sql @@ -0,0 +1,22 @@ +-- CreateTable +CREATE TABLE "EventLogs_WithdrawalQueued" ( + "address" TEXT NOT NULL, + "transactionHash" TEXT NOT NULL, + "transactionIndex" INTEGER NOT NULL, + "blockNumber" BIGINT NOT NULL, + "blockHash" TEXT NOT NULL, + "blockTime" TIMESTAMP(3) NOT NULL, + "withdrawalRoot" TEXT NOT NULL, + "staker" TEXT NOT NULL, + "delegatedTo" TEXT NOT NULL, + "withdrawer" TEXT NOT NULL, + "nonce" BIGINT NOT NULL, + "startBlock" BIGINT NOT NULL, + "strategies" TEXT[], + "shares" TEXT[], + + CONSTRAINT "EventLogs_WithdrawalQueued_pkey" PRIMARY KEY ("transactionHash","transactionIndex") +); + +-- CreateIndex +CREATE INDEX "EventLogs_WithdrawalQueued_withdrawalRoot_idx" ON "EventLogs_WithdrawalQueued"("withdrawalRoot"); diff --git a/packages/prisma/migrations/20240606215914_include_raw_evm_logs_data_withdrawal_completed/migration.sql b/packages/prisma/migrations/20240606215914_include_raw_evm_logs_data_withdrawal_completed/migration.sql new file mode 100644 index 00000000..96536d5e --- /dev/null +++ b/packages/prisma/migrations/20240606215914_include_raw_evm_logs_data_withdrawal_completed/migration.sql @@ -0,0 +1,15 @@ +-- CreateTable +CREATE TABLE "EventLogs_WithdrawalCompleted" ( + "address" TEXT NOT NULL, + "transactionHash" TEXT NOT NULL, + "transactionIndex" INTEGER NOT NULL, + "blockNumber" BIGINT NOT NULL, + "blockHash" TEXT NOT NULL, + "blockTime" TIMESTAMP(3) NOT NULL, + "withdrawalRoot" TEXT NOT NULL, + + CONSTRAINT "EventLogs_WithdrawalCompleted_pkey" PRIMARY KEY ("transactionHash","transactionIndex") +); + +-- CreateIndex +CREATE INDEX "EventLogs_WithdrawalCompleted_withdrawalRoot_idx" ON "EventLogs_WithdrawalCompleted"("withdrawalRoot"); diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 6b6b5c8f..24d6f716 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -305,9 +305,46 @@ model EventLogs_OperatorSharesDecreased { @@index([staker, operator]) } +model EventLogs_WithdrawalQueued { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + withdrawalRoot String + staker String + delegatedTo String + withdrawer String + nonce BigInt + startBlock BigInt + strategies String[] + shares String[] + + @@id([transactionHash, transactionIndex]) + @@index([withdrawalRoot]) +} + +model EventLogs_WithdrawalCompleted { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + withdrawalRoot String + + @@id([transactionHash, transactionIndex]) + @@index([withdrawalRoot]) +} + // Misc model Evm_BlockData { - number BigInt @id + number BigInt @id timestamp DateTime } diff --git a/packages/seeder/src/events/seedLogsWithdrawalCompleted.ts b/packages/seeder/src/events/seedLogsWithdrawalCompleted.ts new file mode 100644 index 00000000..34890c6b --- /dev/null +++ b/packages/seeder/src/events/seedLogsWithdrawalCompleted.ts @@ -0,0 +1,95 @@ +import prisma from '@prisma/client' +import { parseAbiItem } from 'viem' +import { getEigenContracts } from '../data/address' +import { getViemClient } from '../utils/viemClient' +import { + bulkUpdateDbTransactions, + fetchLastSyncBlock, + getBlockDataFromDb, + loopThroughBlocks +} from '../utils/seeder' +import { getPrismaClient } from '../utils/prismaClient' + +const blockSyncKeyLogs = 'lastSyncedBlock_logs_completedWithdrawals' + +/** + * Utility function to seed event logs + * + * @param fromBlock + * @param toBlock + */ +export async function seedLogsWithdrawalCompleted( + toBlock?: bigint, + fromBlock?: bigint +) { + const viemClient = getViemClient() + const prismaClient = getPrismaClient() + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + + let totalSeeded = 0 + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + try { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + const logsWithdrawalCompleted: prisma.EventLogs_WithdrawalCompleted[] = [] + + const logs = await viemClient.getLogs({ + address: getEigenContracts().DelegationManager, + event: parseAbiItem([ + 'event WithdrawalCompleted(bytes32 withdrawalRoot)' + ]), + fromBlock, + toBlock + }) + + // Setup a list containing event data + for (const l in logs) { + const log = logs[l] + + logsWithdrawalCompleted.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + withdrawalRoot: String(log.args.withdrawalRoot) + }) + } + + dbTransactions.push( + prismaClient.eventLogs_WithdrawalCompleted.createMany({ + data: logsWithdrawalCompleted, + skipDuplicates: true + }) + ) + + // Store last synced block + dbTransactions.push( + prismaClient.settings.upsert({ + where: { key: blockSyncKeyLogs }, + update: { value: Number(toBlock) }, + create: { key: blockSyncKeyLogs, value: Number(toBlock) } + }) + ) + + // Update database + const seedLength = logsWithdrawalCompleted.length + + await bulkUpdateDbTransactions( + dbTransactions, + `Withdrawal Completed from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + ) + + totalSeeded += seedLength + } catch (error) {} + }) +} diff --git a/packages/seeder/src/events/seedLogsWithdrawalQueued.ts b/packages/seeder/src/events/seedLogsWithdrawalQueued.ts new file mode 100644 index 00000000..ed16dbdc --- /dev/null +++ b/packages/seeder/src/events/seedLogsWithdrawalQueued.ts @@ -0,0 +1,103 @@ +import prisma from '@prisma/client' +import { parseAbiItem } from 'viem' +import { getEigenContracts } from '../data/address' +import { getViemClient } from '../utils/viemClient' +import { + bulkUpdateDbTransactions, + fetchLastSyncBlock, + getBlockDataFromDb, + loopThroughBlocks +} from '../utils/seeder' +import { getPrismaClient } from '../utils/prismaClient' + +const blockSyncKeyLogs = 'lastSyncedBlock_logs_queuedWithdrawals' + +/** + * Utility function to seed event logs + * + * @param fromBlock + * @param toBlock + */ +export async function seedLogsWithdrawalQueued( + toBlock?: bigint, + fromBlock?: bigint +) { + const viemClient = getViemClient() + const prismaClient = getPrismaClient() + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + + let totalSeeded = 0 + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + try { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + const logsWithdrawalQueued: prisma.EventLogs_WithdrawalQueued[] = [] + + const logs = await viemClient.getLogs({ + address: getEigenContracts().DelegationManager, + event: parseAbiItem([ + 'event WithdrawalQueued(bytes32 withdrawalRoot, Withdrawal withdrawal)', + 'struct Withdrawal { address staker; address delegatedTo; address withdrawer; uint256 nonce; uint32 startBlock; address[] strategies; uint256[] shares; }' + ]), + fromBlock, + toBlock + }) + + // Setup a list containing event data + for (const l in logs) { + const log = logs[l] + + logsWithdrawalQueued.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + withdrawalRoot: String(log.args.withdrawalRoot), + staker: String(log.args.withdrawal?.staker), + delegatedTo: String(log.args.withdrawal?.delegatedTo), + withdrawer: String(log.args.withdrawal?.withdrawer), + nonce: log.args.withdrawal?.nonce || 0n, + startBlock: BigInt(log.args.withdrawal?.startBlock || 0), + strategies: (log.args.withdrawal?.strategies as string[]) || [], + shares: log.args.withdrawal?.shares.map((s) => s.toString()) || [] + }) + } + + dbTransactions.push( + prismaClient.eventLogs_WithdrawalQueued.createMany({ + data: logsWithdrawalQueued, + skipDuplicates: true + }) + ) + + // Store last synced block + dbTransactions.push( + prismaClient.settings.upsert({ + where: { key: blockSyncKeyLogs }, + update: { value: Number(toBlock) }, + create: { key: blockSyncKeyLogs, value: Number(toBlock) } + }) + ) + + // Update database + const seedLength = logsWithdrawalQueued.length + + await bulkUpdateDbTransactions( + dbTransactions, + `Withdrawal Queued from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + ) + + totalSeeded += seedLength + } catch (error) {} + }) +} diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 3876088d..d3cf7d3f 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -17,6 +17,8 @@ import { seedOperatorShares } from './seedOperatorShares' import { seedValidators } from './seedValidators' import { seedQueuedWithdrawals } from './seedWithdrawalsQueued' import { seedCompletedWithdrawals } from './seedWithdrawalsCompleted' +import { seedLogsWithdrawalQueued } from './events/seedLogsWithdrawalQueued' +import { seedLogsWithdrawalCompleted } from './events/seedLogsWithdrawalCompleted' console.log('Initializing seeder ...') @@ -24,12 +26,12 @@ function delay(seconds: number) { return new Promise((resolve) => setTimeout(resolve, seconds * 1000)) } -async function seedEventLogsLoop() { +async function seedEigenDataLoop() { while (true) { try { const viemClient = getViemClient() const targetBlock = await viemClient.getBlockNumber() - console.log('Seeding Block and Log Data ...', targetBlock) + console.log('Seeding Data ...', targetBlock) await seedBlockData(targetBlock) await seedLogsAVSMetadata(targetBlock) @@ -38,21 +40,8 @@ async function seedEventLogsLoop() { await seedLogsOperatorShares(targetBlock) await seedLogsStakerDelegation(targetBlock) await seedLogsPodDeployed(targetBlock) - } catch (error) { - console.log('Failed to seed Block and Log Data at:', Date.now()) - console.log(error) - } - - await delay(30) - } -} - -async function seedEigenDataLoop() { - await delay(60) - - while (true) { - try { - console.log('Seeding Eigen Data ...') + await seedLogsWithdrawalQueued(targetBlock) + await seedLogsWithdrawalCompleted(targetBlock) await seedAvs() await seedOperators() @@ -62,16 +51,16 @@ async function seedEigenDataLoop() { await seedQueuedWithdrawals() await seedCompletedWithdrawals() } catch (error) { - console.log('Failed to seed AVS and Operators at:', Date.now()) + console.log('Failed to seed data at:', Date.now()) console.log(error) } - await delay(120) // Wait for 2 minutes (120 seconds) + await delay(30) } } async function seedEigenPodValidators() { - await delay(60) + await delay(120) while (true) { try { @@ -88,6 +77,5 @@ async function seedEigenPodValidators() { } } -seedEventLogsLoop() seedEigenDataLoop() seedEigenPodValidators() diff --git a/packages/seeder/src/seedWithdrawalsCompleted.ts b/packages/seeder/src/seedWithdrawalsCompleted.ts index 21a2fb2d..3bd03ce9 100644 --- a/packages/seeder/src/seedWithdrawalsCompleted.ts +++ b/packages/seeder/src/seedWithdrawalsCompleted.ts @@ -1,15 +1,12 @@ -import { parseAbiItem } from 'viem' -import { getEigenContracts } from './data/address' -import { getViemClient } from './utils/viemClient' import { getPrismaClient } from './utils/prismaClient' import { bulkUpdateDbTransactions, fetchLastSyncBlock, - loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' const blockSyncKey = 'lastSyncedBlock_completedWithdrawals' +const blockSyncKeyLogs = 'lastSyncedBlock_logs_completedWithdrawals' /** * @@ -20,41 +17,47 @@ export async function seedCompletedWithdrawals( toBlock?: bigint, fromBlock?: bigint ) { - console.log('Seeding Completed Withdrawals ...') - - const viemClient = getViemClient() const prismaClient = getPrismaClient() const completedWithdrawalList: string[] = [] const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - - // Loop through evm logs - await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - const logs = await viemClient.getLogs({ - address: getEigenContracts().DelegationManager, - event: parseAbiItem('event WithdrawalCompleted(bytes32 withdrawalRoot)'), - fromBlock, - toBlock - }) + const lastBlock = toBlock + ? toBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) - for (const l in logs) { - const log = logs[l] + // Bail early if there is no block diff to sync + if (lastBlock - firstBlock <= 0) { + console.log(`Completed Withdrawals in sync ${firstBlock} - ${lastBlock}`) + return + } - const withdrawalRoot = log.args.withdrawalRoot + console.log(`Seeding Completed Withdrawals from ${firstBlock} - ${lastBlock}`) - if (withdrawalRoot) { - completedWithdrawalList.push(withdrawalRoot) + const logs = await prismaClient.eventLogs_WithdrawalCompleted.findMany({ + where: { + blockNumber: { + gt: firstBlock, + lte: lastBlock } } - - console.log( - `Withdrawals completed between blocks ${fromBlock} ${toBlock}: ${logs.length}` - ) }) + for (const l in logs) { + const log = logs[l] + + const withdrawalRoot = log.withdrawalRoot + + if (withdrawalRoot) { + completedWithdrawalList.push(withdrawalRoot) + } + } + + console.log( + `Withdrawals completed between blocks ${firstBlock} ${lastBlock}: ${logs.length}` + ) + // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] diff --git a/packages/seeder/src/seedWithdrawalsQueued.ts b/packages/seeder/src/seedWithdrawalsQueued.ts index 00f13450..e5c87318 100644 --- a/packages/seeder/src/seedWithdrawalsQueued.ts +++ b/packages/seeder/src/seedWithdrawalsQueued.ts @@ -1,32 +1,13 @@ import prisma from '@prisma/client' -import { parseAbiItem } from 'viem' -import { getEigenContracts } from './data/address' -import { getViemClient } from './utils/viemClient' import { getPrismaClient } from './utils/prismaClient' import { bulkUpdateDbTransactions, fetchLastSyncBlock, - loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' const blockSyncKey = 'lastSyncedBlock_queuedWithdrawals' - -interface Withdrawal { - withdrawalRoot: string - nonce: number - isCompleted: boolean - - stakerAddress: string - delegatedTo: string - withdrawerAddress: string - strategies: string[] - shares: string[] - startBlock: number - - createdAtBlock: number - updatedAtBlock: number -} +const blockSyncKeyLogs = 'lastSyncedBlock_logs_queuedWithdrawals' /** * @@ -37,70 +18,69 @@ export async function seedQueuedWithdrawals( toBlock?: bigint, fromBlock?: bigint ) { - console.log('Seeding Queued Withdrawals ...') - - const viemClient = getViemClient() const prismaClient = getPrismaClient() const queuedWithdrawalList: prisma.Withdrawal[] = [] const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - - // Loop through evm logs - await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - const logs = await viemClient.getLogs({ - address: getEigenContracts().DelegationManager, - event: parseAbiItem([ - 'event WithdrawalQueued(bytes32 withdrawalRoot, Withdrawal withdrawal)', - 'struct Withdrawal { address staker; address delegatedTo; address withdrawer; uint256 nonce; uint32 startBlock; address[] strategies; uint256[] shares; }' - ]), - fromBlock, - toBlock - }) - - for (const l in logs) { - const log = logs[l] - - const withdrawalRoot = log.args.withdrawalRoot - const withdrawal = log.args.withdrawal - - const blockNumber = BigInt(log.blockNumber) - const block = await viemClient.getBlock({ blockNumber: blockNumber }) - const timestamp = new Date(Number(block.timestamp) * 1000) - - if (withdrawalRoot && withdrawal) { - const stakerAddress = withdrawal.staker.toLowerCase() - const delegatedTo = withdrawal.delegatedTo.toLowerCase() - const withdrawerAddress = withdrawal.withdrawer.toLowerCase() - - queuedWithdrawalList.push({ - withdrawalRoot, - nonce: Number(withdrawal.nonce), - isCompleted: false, - stakerAddress, - delegatedTo, - withdrawerAddress, - strategies: withdrawal.strategies.map((s) => - s.toLowerCase() - ) as string[], - shares: withdrawal.shares.map((s) => BigInt(s).toString()), - - startBlock: BigInt(withdrawal.startBlock), - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) + const lastBlock = toBlock + ? toBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + + // Bail early if there is no block diff to sync + if (lastBlock - firstBlock <= 0) { + console.log(`Queued Withdrawals in sync ${firstBlock} - ${lastBlock}`) + return + } + + console.log(`Seeding Queued Withdrawals from ${firstBlock} - ${lastBlock}`) + + const logs = await prismaClient.eventLogs_WithdrawalQueued.findMany({ + where: { + blockNumber: { + gt: firstBlock, + lte: lastBlock } } - - console.log( - `Withdrawals queued between blocks ${fromBlock} ${toBlock}: ${logs.length}` - ) }) + for (const l in logs) { + const log = logs[l] + + const withdrawalRoot = log.withdrawalRoot + + const blockNumber = BigInt(log.blockNumber) + const timestamp = log.blockTime + + if (withdrawalRoot) { + const stakerAddress = log.staker.toLowerCase() + const delegatedTo = log.delegatedTo.toLowerCase() + const withdrawerAddress = log.withdrawer.toLowerCase() + + queuedWithdrawalList.push({ + withdrawalRoot, + nonce: Number(log.nonce), + isCompleted: false, + stakerAddress, + delegatedTo, + withdrawerAddress, + strategies: log.strategies.map((s) => s.toLowerCase()) as string[], + shares: log.shares.map((s) => s.toString()), + + startBlock: log.startBlock, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) + } + } + + console.log( + `Withdrawals queued between blocks ${firstBlock} ${lastBlock}: ${logs.length}` + ) + // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] From ed8c32bd65ca76884ea91e064274535ee2b5ee5a Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Fri, 7 Jun 2024 03:54:17 +0530 Subject: [PATCH 39/62] Updated logs --- packages/seeder/src/blocks/seedBlockData.ts | 2 +- .../seeder/src/events/seedLogsAVSMetadata.ts | 6 +----- .../seedLogsOperatorAVSRegistrationStatus.ts | 6 +----- .../src/events/seedLogsOperatorMetadata.ts | 6 +----- .../seeder/src/events/seedLogsOperatorShares.ts | 6 +----- .../seeder/src/events/seedLogsPodDeployed.ts | 6 +----- .../src/events/seedLogsStakerDelegation.ts | 4 +--- .../src/events/seedLogsWithdrawalCompleted.ts | 6 +----- .../src/events/seedLogsWithdrawalQueued.ts | 6 +----- packages/seeder/src/index.ts | 6 +++--- packages/seeder/src/seedAvs.ts | 17 +++++++---------- packages/seeder/src/seedAvsOperators.ts | 17 +++++++---------- packages/seeder/src/seedOperatorShares.ts | 17 +++++++---------- packages/seeder/src/seedOperators.ts | 17 +++++++---------- packages/seeder/src/seedPods.ts | 15 +++++---------- packages/seeder/src/seedStakers.ts | 15 +++++---------- packages/seeder/src/seedWithdrawalsCompleted.ts | 17 +++++++---------- packages/seeder/src/seedWithdrawalsQueued.ts | 12 ++---------- 18 files changed, 59 insertions(+), 122 deletions(-) diff --git a/packages/seeder/src/blocks/seedBlockData.ts b/packages/seeder/src/blocks/seedBlockData.ts index 52c52f82..1f3d66f9 100644 --- a/packages/seeder/src/blocks/seedBlockData.ts +++ b/packages/seeder/src/blocks/seedBlockData.ts @@ -53,7 +53,7 @@ export async function seedBlockData(toBlock?: bigint, fromBlock?: bigint) { skipDuplicates: true }) ], - `Block data from: ${fromBlock} to: ${toBlock} size: ${Number( + `[Meta] Block data from: ${fromBlock} to: ${toBlock} size: ${Number( toBlock - fromBlock )}` ) diff --git a/packages/seeder/src/events/seedLogsAVSMetadata.ts b/packages/seeder/src/events/seedLogsAVSMetadata.ts index 7f056d85..15f916d9 100644 --- a/packages/seeder/src/events/seedLogsAVSMetadata.ts +++ b/packages/seeder/src/events/seedLogsAVSMetadata.ts @@ -31,8 +31,6 @@ export async function seedLogsAVSMetadata( const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) - let totalSeeded = 0 - // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { @@ -89,10 +87,8 @@ export async function seedLogsAVSMetadata( await bulkUpdateDbTransactions( dbTransactions, - `AVS Metadata from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + `[Logs] AVS Metadata from: ${fromBlock} to: ${toBlock} size: ${seedLength}` ) - - totalSeeded += seedLength } catch (error) {} }) } diff --git a/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts b/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts index 96c1c73a..47ed0c1a 100644 --- a/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts +++ b/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts @@ -31,8 +31,6 @@ export async function seedLogsOperatorAVSRegistrationStatus( const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) - let totalSeeded = 0 - // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { @@ -91,10 +89,8 @@ export async function seedLogsOperatorAVSRegistrationStatus( await bulkUpdateDbTransactions( dbTransactions, - `Operator Registration from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + `[Logs] Operator Registration from: ${fromBlock} to: ${toBlock} size: ${seedLength}` ) - - totalSeeded += seedLength } catch (error) {} }) } diff --git a/packages/seeder/src/events/seedLogsOperatorMetadata.ts b/packages/seeder/src/events/seedLogsOperatorMetadata.ts index 4a2f3d1c..5e8e2f76 100644 --- a/packages/seeder/src/events/seedLogsOperatorMetadata.ts +++ b/packages/seeder/src/events/seedLogsOperatorMetadata.ts @@ -31,8 +31,6 @@ export async function seedLogsOperatorMetadata( const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) - let totalSeeded = 0 - // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { @@ -89,10 +87,8 @@ export async function seedLogsOperatorMetadata( await bulkUpdateDbTransactions( dbTransactions, - `Operator Metadata from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + `[Logs] Operator Metadata from: ${fromBlock} to: ${toBlock} size: ${seedLength}` ) - - totalSeeded += seedLength } catch (error) {} }) } diff --git a/packages/seeder/src/events/seedLogsOperatorShares.ts b/packages/seeder/src/events/seedLogsOperatorShares.ts index 0f58ea6b..5c69b035 100644 --- a/packages/seeder/src/events/seedLogsOperatorShares.ts +++ b/packages/seeder/src/events/seedLogsOperatorShares.ts @@ -31,8 +31,6 @@ export async function seedLogsOperatorShares( const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) - let totalSeeded = 0 - // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { @@ -117,10 +115,8 @@ export async function seedLogsOperatorShares( await bulkUpdateDbTransactions( dbTransactions, - `Operator Shares from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + `[Logs] Operator Shares from: ${fromBlock} to: ${toBlock} size: ${seedLength}` ) - - totalSeeded += seedLength } catch (error) {} }) } diff --git a/packages/seeder/src/events/seedLogsPodDeployed.ts b/packages/seeder/src/events/seedLogsPodDeployed.ts index 7d3cc23c..2c99ab50 100644 --- a/packages/seeder/src/events/seedLogsPodDeployed.ts +++ b/packages/seeder/src/events/seedLogsPodDeployed.ts @@ -31,8 +31,6 @@ export async function seedLogsPodDeployed( const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) - let totalSeeded = 0 - // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { @@ -89,10 +87,8 @@ export async function seedLogsPodDeployed( await bulkUpdateDbTransactions( dbTransactions, - `Pod Deployed from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + `[Logs] Pod Deployed from: ${fromBlock} to: ${toBlock} size: ${seedLength}` ) - - totalSeeded += seedLength } catch (error) {} }) } diff --git a/packages/seeder/src/events/seedLogsStakerDelegation.ts b/packages/seeder/src/events/seedLogsStakerDelegation.ts index 9c3adf13..fc4ff6c9 100644 --- a/packages/seeder/src/events/seedLogsStakerDelegation.ts +++ b/packages/seeder/src/events/seedLogsStakerDelegation.ts @@ -112,10 +112,8 @@ export async function seedLogsStakerDelegation( await bulkUpdateDbTransactions( dbTransactions, - `Staker Delegation from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + `[Logs] Staker Delegation from: ${fromBlock} to: ${toBlock} size: ${seedLength}` ) - - totalSeeded += seedLength } catch (error) {} }) } diff --git a/packages/seeder/src/events/seedLogsWithdrawalCompleted.ts b/packages/seeder/src/events/seedLogsWithdrawalCompleted.ts index 34890c6b..16736856 100644 --- a/packages/seeder/src/events/seedLogsWithdrawalCompleted.ts +++ b/packages/seeder/src/events/seedLogsWithdrawalCompleted.ts @@ -31,8 +31,6 @@ export async function seedLogsWithdrawalCompleted( const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) - let totalSeeded = 0 - // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { @@ -86,10 +84,8 @@ export async function seedLogsWithdrawalCompleted( await bulkUpdateDbTransactions( dbTransactions, - `Withdrawal Completed from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + `[Logs] Withdrawal Completed from: ${fromBlock} to: ${toBlock} size: ${seedLength}` ) - - totalSeeded += seedLength } catch (error) {} }) } diff --git a/packages/seeder/src/events/seedLogsWithdrawalQueued.ts b/packages/seeder/src/events/seedLogsWithdrawalQueued.ts index ed16dbdc..1c9ea9cc 100644 --- a/packages/seeder/src/events/seedLogsWithdrawalQueued.ts +++ b/packages/seeder/src/events/seedLogsWithdrawalQueued.ts @@ -31,8 +31,6 @@ export async function seedLogsWithdrawalQueued( const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() const blockData = await getBlockDataFromDb(firstBlock, lastBlock) - let totalSeeded = 0 - // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { try { @@ -94,10 +92,8 @@ export async function seedLogsWithdrawalQueued( await bulkUpdateDbTransactions( dbTransactions, - `Withdrawal Queued from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + `[Logs] Withdrawal Queued from: ${fromBlock} to: ${toBlock} size: ${seedLength}` ) - - totalSeeded += seedLength } catch (error) {} }) } diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index d3cf7d3f..40a69268 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -31,7 +31,7 @@ async function seedEigenDataLoop() { try { const viemClient = getViemClient() const targetBlock = await viemClient.getBlockNumber() - console.log('Seeding Data ...', targetBlock) + console.log('\nSeeding Data ...', targetBlock) await seedBlockData(targetBlock) await seedLogsAVSMetadata(targetBlock) @@ -55,7 +55,7 @@ async function seedEigenDataLoop() { console.log(error) } - await delay(30) + await delay(60) } } @@ -64,7 +64,7 @@ async function seedEigenPodValidators() { while (true) { try { - console.log('Seeding Eigen Pods Data ...') + console.log('\nSeeding Eigen Pods Data ...') await seedPods() await seedValidators() diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index b8faff90..62aaaa96 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -39,12 +39,12 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { // Bail early if there is no block diff to sync if (lastBlock - firstBlock <= 0) { - console.log(`AVS in sync ${firstBlock} - ${lastBlock}`) + console.log( + `[In Sync] [Data] AVS MetadataURI from: ${firstBlock} to: ${lastBlock}` + ) return } - console.log(`Seeding AVS from ${firstBlock} - ${lastBlock}`) - const logs = await prismaClient.eventLogs_AVSMetadataURIUpdated.findMany({ where: { blockNumber: { @@ -109,10 +109,6 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { } } - console.log( - `Avs registered between blocks ${firstBlock} ${lastBlock}: ${logs.length}` - ) - // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -186,10 +182,11 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { } } - await bulkUpdateDbTransactions(dbTransactions) + await bulkUpdateDbTransactions( + dbTransactions, + `[Data] AVS MetadataURI from: ${firstBlock} to: ${lastBlock} size: ${avsList.size}` + ) // Storing last synced block await saveLastSyncBlock(blockSyncKey, lastBlock) - - console.log('Seeded AVS:', avsList.size) } diff --git a/packages/seeder/src/seedAvsOperators.ts b/packages/seeder/src/seedAvsOperators.ts index ac6b5f17..65f4bddd 100644 --- a/packages/seeder/src/seedAvsOperators.ts +++ b/packages/seeder/src/seedAvsOperators.ts @@ -22,12 +22,12 @@ export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { // Bail early if there is no block diff to sync if (lastBlock - firstBlock <= 0) { - console.log(`AVSOperators in sync ${firstBlock} - ${lastBlock}`) + console.log( + `[In Sync] [Data] AVS Operators from: ${firstBlock} to: ${lastBlock}` + ) return } - console.log(`Seeding AVSOperators from ${firstBlock} - ${lastBlock}`) - // Load initial operator staker state const avs = await prismaClient.avs.findMany({ select: { address: true } @@ -56,10 +56,6 @@ export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { } } - console.log( - `Avs operators updated between blocks ${firstBlock} ${lastBlock}: ${logs.length}` - ) - // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -111,10 +107,11 @@ export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { } } - await bulkUpdateDbTransactions(dbTransactions) + await bulkUpdateDbTransactions( + dbTransactions, + `[Data] AVS Operator from: ${firstBlock} to: ${lastBlock} size: ${avsOperatorsList.size}` + ) // Storing last sycned block await saveLastSyncBlock(blockSyncKey, lastBlock) - - console.log('Seeded AVS Operators:', avsOperatorsList.size) } diff --git a/packages/seeder/src/seedOperatorShares.ts b/packages/seeder/src/seedOperatorShares.ts index 7042b83e..d999182c 100644 --- a/packages/seeder/src/seedOperatorShares.ts +++ b/packages/seeder/src/seedOperatorShares.ts @@ -26,12 +26,12 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { // Bail early if there is no block diff to sync if (lastBlock - firstBlock <= 0) { - console.log(`Operator Shares in sync ${firstBlock} - ${lastBlock}`) + console.log( + `[In Sync] [Data] Operator Shares from: ${firstBlock} to: ${lastBlock}` + ) return } - console.log(`Seeding Operator Shares from ${firstBlock} - ${lastBlock}`) - if (firstBlock === baseBlock) { await prismaClient.operatorStrategyShares.deleteMany() } @@ -133,10 +133,6 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { } } - console.log( - `Operator shares updated between blocks ${firstBlock} ${lastBlock}: ${logs.length}` - ) - // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -191,10 +187,11 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { } } - await bulkUpdateDbTransactions(dbTransactions) + await bulkUpdateDbTransactions( + dbTransactions, + `[Data] Operator Shares from: ${firstBlock} to: ${lastBlock} size: ${operatorShares.size}` + ) // Storing last sycned block await saveLastSyncBlock(blockSyncKey, lastBlock) - - console.log('Seeded operator shares:', operatorShares.size) } diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index 6731675b..cc95275e 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -37,12 +37,12 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { // Bail early if there is no block diff to sync if (lastBlock - firstBlock <= 0) { - console.log(`Operators in sync ${firstBlock} - ${lastBlock}`) + console.log( + `[In Sync] [Data] Operator MetadataURI from: ${firstBlock} to: ${lastBlock}` + ) return } - console.log(`Seeding Operators from ${firstBlock} - ${lastBlock}`) - const logs = await prismaClient.eventLogs_OperatorMetadataURIUpdated.findMany( { where: { @@ -109,10 +109,6 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { } } - console.log( - `Operators registered between blocks ${firstBlock} ${lastBlock}: ${logs.length}` - ) - // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -186,10 +182,11 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { } } - await bulkUpdateDbTransactions(dbTransactions) + await bulkUpdateDbTransactions( + dbTransactions, + `[Data] Operator MetadataURI from: ${firstBlock} to: ${lastBlock} size: ${operatorList.size}` + ) // Storing last synced block await saveLastSyncBlock(blockSyncKey, lastBlock) - - console.log('Seeded operators:', operatorList.size) } diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index d63d20ac..f1cf0ad9 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -28,12 +28,10 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { // Bail early if there is no block diff to sync if (lastBlock - firstBlock <= 0) { - console.log(`Pods in sync ${firstBlock} - ${lastBlock}`) + console.log(`[In Sync] [Data] Pods from: ${firstBlock} to: ${lastBlock}`) return } - console.log(`Seeding Pods from ${firstBlock} - ${lastBlock}`) - const logs = await prismaClient.eventLogs_PodDeployed.findMany({ where: { blockNumber: { @@ -63,10 +61,6 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { }) } - console.log( - `Pods deployed between blocks ${firstBlock} ${lastBlock}: ${logs.length}` - ) - // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -106,10 +100,11 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { }) } - await bulkUpdateDbTransactions(dbTransactions) + await bulkUpdateDbTransactions( + dbTransactions, + `[Data] AVS MetadataURI from: ${firstBlock} to: ${lastBlock} size: ${podList.length}` + ) // Storing last sycned block await saveLastSyncBlock(blockSyncKey, lastBlock) - - console.log('Seeded Pods:', podList.length) } diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index bc0e042f..203175c0 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -33,12 +33,10 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { // Bail early if there is no block diff to sync if (lastBlock - firstBlock <= 0) { - console.log(`Stakers in sync ${firstBlock} - ${lastBlock}`) + console.log(`[In Sync] [Data] Stakers from: ${firstBlock} to: ${lastBlock}`) return } - console.log(`Seeding Stakers from ${firstBlock} - ${lastBlock}`) - if (firstBlock === baseBlock) { await prismaClient.stakerStrategyShares.deleteMany() } @@ -217,10 +215,6 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } } - console.log( - `Stakers deployed between blocks ${firstBlock} ${lastBlock}: ${logs.length}` - ) - // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -308,10 +302,11 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { } } - await bulkUpdateDbTransactions(dbTransactions) + await bulkUpdateDbTransactions( + dbTransactions, + `[Data] Stakers from: ${firstBlock} to: ${lastBlock} size: ${stakers.size}` + ) // Storing last sycned block await saveLastSyncBlock(blockSyncKey, lastBlock) - - console.log('Seeded stakers:', stakers.size) } diff --git a/packages/seeder/src/seedWithdrawalsCompleted.ts b/packages/seeder/src/seedWithdrawalsCompleted.ts index 3bd03ce9..0b1a56ff 100644 --- a/packages/seeder/src/seedWithdrawalsCompleted.ts +++ b/packages/seeder/src/seedWithdrawalsCompleted.ts @@ -29,12 +29,12 @@ export async function seedCompletedWithdrawals( // Bail early if there is no block diff to sync if (lastBlock - firstBlock <= 0) { - console.log(`Completed Withdrawals in sync ${firstBlock} - ${lastBlock}`) + console.log( + `[In Sync] [Data] Completed Withdrawal from: ${firstBlock} to: ${lastBlock}` + ) return } - console.log(`Seeding Completed Withdrawals from ${firstBlock} - ${lastBlock}`) - const logs = await prismaClient.eventLogs_WithdrawalCompleted.findMany({ where: { blockNumber: { @@ -54,10 +54,6 @@ export async function seedCompletedWithdrawals( } } - console.log( - `Withdrawals completed between blocks ${firstBlock} ${lastBlock}: ${logs.length}` - ) - // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -73,10 +69,11 @@ export async function seedCompletedWithdrawals( ) } - await bulkUpdateDbTransactions(dbTransactions) + await bulkUpdateDbTransactions( + dbTransactions, + `[Data] Completed Withdrawal from: ${firstBlock} to: ${lastBlock} size: ${completedWithdrawalList.length}` + ) // // Storing last sycned block await saveLastSyncBlock(blockSyncKey, lastBlock) - - console.log('Seeded Completed Withdrawals:', completedWithdrawalList.length) } diff --git a/packages/seeder/src/seedWithdrawalsQueued.ts b/packages/seeder/src/seedWithdrawalsQueued.ts index e5c87318..3a109825 100644 --- a/packages/seeder/src/seedWithdrawalsQueued.ts +++ b/packages/seeder/src/seedWithdrawalsQueued.ts @@ -30,12 +30,10 @@ export async function seedQueuedWithdrawals( // Bail early if there is no block diff to sync if (lastBlock - firstBlock <= 0) { - console.log(`Queued Withdrawals in sync ${firstBlock} - ${lastBlock}`) + console.log(`[In Sync] [Data] Queued Withdrawal from: ${firstBlock} to: ${lastBlock}`) return } - console.log(`Seeding Queued Withdrawals from ${firstBlock} - ${lastBlock}`) - const logs = await prismaClient.eventLogs_WithdrawalQueued.findMany({ where: { blockNumber: { @@ -77,10 +75,6 @@ export async function seedQueuedWithdrawals( } } - console.log( - `Withdrawals queued between blocks ${firstBlock} ${lastBlock}: ${logs.length}` - ) - // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -94,10 +88,8 @@ export async function seedQueuedWithdrawals( ) } - await bulkUpdateDbTransactions(dbTransactions) + await bulkUpdateDbTransactions(dbTransactions, `[Data] Queued Withdrawal from: ${firstBlock} to: ${lastBlock} size: ${queuedWithdrawalList.length}`) // // Storing last sycned block await saveLastSyncBlock(blockSyncKey, lastBlock) - - console.log('Seeded Queued Withdrawals:', queuedWithdrawalList.length) } From 044503ebc351660a5e8b848af69b1f839c6ce57f Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 7 Jun 2024 10:52:07 +0530 Subject: [PATCH 40/62] deposit seeding integration for seeder v2 --- packages/prisma/schema.prisma | 20 ++- packages/seeder/src/events/seedLogsDeposit.ts | 92 +++++++++++ packages/seeder/src/seedDeposits.ts | 154 +++++------------- 3 files changed, 150 insertions(+), 116 deletions(-) create mode 100644 packages/seeder/src/events/seedLogsDeposit.ts diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 1173972d..1bb80cca 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -116,7 +116,7 @@ model StakerStrategyShares { } model Deposit { - txHash String @id @unique + transactionHash String @id @unique stakerAddress String tokenAddress String strategyAddress String @@ -353,6 +353,24 @@ model EventLogs_WithdrawalCompleted { @@index([withdrawalRoot]) } +model EventLogs_Deposit { + address String + + transactionHash String + transactionIndex Int + blockNumber BigInt + blockHash String + blockTime DateTime + + staker String + token String + strategy String + shares String + + @@id([transactionHash, transactionIndex]) + @@index([staker]) +} + // Misc model Evm_BlockData { diff --git a/packages/seeder/src/events/seedLogsDeposit.ts b/packages/seeder/src/events/seedLogsDeposit.ts new file mode 100644 index 00000000..acc505cf --- /dev/null +++ b/packages/seeder/src/events/seedLogsDeposit.ts @@ -0,0 +1,92 @@ +import prisma from '@prisma/client' +import { parseAbiItem } from 'viem' +import { getEigenContracts } from '../data/address' +import { getViemClient } from '../utils/viemClient' +import { + bulkUpdateDbTransactions, + fetchLastSyncBlock, + getBlockDataFromDb, + loopThroughBlocks +} from '../utils/seeder' +import { getPrismaClient } from '../utils/prismaClient' + +const blockSyncKeyLogs = 'lastSyncedBlock_logs_deposit' + +/** + * Utility function to seed event logs + * + * @param fromBlock + * @param toBlock + */ +export async function seedLogsDeposit(toBlock?: bigint, fromBlock?: bigint) { + const viemClient = getViemClient() + const prismaClient = getPrismaClient() + + const firstBlock = fromBlock + ? fromBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() + const blockData = await getBlockDataFromDb(firstBlock, lastBlock) + + // Loop through evm logs + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + try { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + const logsDeposit: prisma.EventLogs_Deposit[] = [] + + const logs = await viemClient.getLogs({ + address: [getEigenContracts().StrategyManager], + events: [ + parseAbiItem( + 'event Deposit(address staker, address token, address strategy, uint256 shares)' + ) + ], + fromBlock, + toBlock + }) + + // Setup a list containing event data + for (const l in logs) { + const log = logs[l] + + logsDeposit.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.transactionIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + staker: String(log.args.staker), + token: String(log.args.token), + strategy: String(log.args.strategy), + shares: String(log.args.shares) + }) + } + + dbTransactions.push( + prismaClient.eventLogs_Deposit.createMany({ + data: logsDeposit, + skipDuplicates: true + }) + ) + + // Store last synced block + dbTransactions.push( + prismaClient.settings.upsert({ + where: { key: blockSyncKeyLogs }, + update: { value: Number(toBlock) }, + create: { key: blockSyncKeyLogs, value: Number(toBlock) } + }) + ) + + // Update database + const seedLength = logsDeposit.length + + await bulkUpdateDbTransactions( + dbTransactions, + `[Logs] Deposit from: ${fromBlock} to: ${toBlock} size: ${seedLength}` + ) + } catch (error) {} + }) +} diff --git a/packages/seeder/src/seedDeposits.ts b/packages/seeder/src/seedDeposits.ts index 7091ba55..82fe6767 100644 --- a/packages/seeder/src/seedDeposits.ts +++ b/packages/seeder/src/seedDeposits.ts @@ -1,151 +1,75 @@ import prisma from '@prisma/client' -import { parseAbiItem } from 'viem' -import { getEigenContracts } from './data/address' -import { getViemClient } from './utils/viemClient' import { getPrismaClient } from './utils/prismaClient' import { - baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, - loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' const blockSyncKey = 'lastSyncedBlock_deposit' +const blockSyncKeyLogs = 'lastSyncedBlock_logs_deposit' -interface DepositEntryRecord { - txHash: string - staker: string - token: string - strategy: string - shares: string - createdAtBlock: bigint - createdAt: Date -} - -/** - * Utility function to seed deposits from Deposit events emmited by StrategyManager - * - * @param fromBlock - * @param toBlock - */ export async function seedDeposits(toBlock?: bigint, fromBlock?: bigint) { - console.log('Seeding Deposits ...') - - const viemClient = getViemClient() const prismaClient = getPrismaClient() - const depositList: DepositEntryRecord[] = [] + const depositList: prisma.Deposit[] = [] const firstBlock = fromBlock ? fromBlock : await fetchLastSyncBlock(blockSyncKey) - const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - - // Loop through evm logs - await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { - const logs = await viemClient.getLogs({ - address: getEigenContracts().StrategyManager, - event: parseAbiItem( - 'event Deposit(address staker, address token, address strategy, uint256 shares)' - ), - fromBlock, - toBlock - }) - - for (const l in logs) { - const log = logs[l] - - try { - const blockNumber = BigInt(log.blockNumber) - const block = await viemClient.getBlock({ blockNumber: blockNumber }) - const timestamp = new Date(Number(block.timestamp) * 1000) + const lastBlock = toBlock + ? toBlock + : await fetchLastSyncBlock(blockSyncKeyLogs) + + // Bail early if there is no block diff to sync + if (lastBlock - firstBlock <= 0) { + console.log(`[In Sync] [Data] Deposit from: ${firstBlock} to: ${lastBlock}`) + return + } - depositList.push({ - txHash: String(log.transactionHash).toLowerCase(), - stakerAddress: String(log.args.staker).toLowerCase(), - tokenAddress: String(log.args.token).toLowerCase(), - strategyAddress: String(log.args.strategy).toLowerCase(), - shares: String(log.args.shares), - createdAtBlock: blockNumber, - createdAt: timestamp - }) - } catch (error) { - console.log('Failed to seed deposit: ', error) + const logs = await prismaClient.eventLogs_Deposit.findMany({ + where: { + blockNumber: { + gt: firstBlock, + lte: lastBlock } } - - console.log( - `Deposits registered between blocks ${fromBlock} ${toBlock}: ${logs.length}` - ) }) - // Prepare db transaction object - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] + for (const l in logs) { + const log = logs[l] - if (firstBlock === baseBlock) { - dbTransactions.push(prismaClient.deposit.deleteMany()) + const blockNumber = BigInt(log.blockNumber) + const timestamp = log.blockTime - const newDeposit: prisma.Deposit[] = [] + depositList.push({ + transactionHash: log.transactionHash.toLowerCase(), + stakerAddress: log.staker.toLowerCase(), + tokenAddress: log.token.toLowerCase(), + strategyAddress: log.strategy.toLowerCase(), + shares: log.shares, + createdAtBlock: blockNumber, + createdAt: timestamp + }) + } - for (const { - txHash, - stakerAddress, - tokenAddress, - strategyAddress, - shares, - createdAtBlock, - createdAt - } of depositList) { - newDeposit.push({ - txHash, - stakerAddress, - tokenAddress, - strategyAddress, - shares, - createdAtBlock, - createdAt - }) - } + // Prepare db transaction object + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + if (depositList.length > 0) { dbTransactions.push( prismaClient.deposit.createMany({ - data: newDeposit, + data: depositList, skipDuplicates: true }) ) - } else { - for (const { - txHash, - stakerAddress, - tokenAddress, - strategyAddress, - shares, - createdAtBlock, - createdAt - } of depositList) { - dbTransactions.push( - prismaClient.deposit.upsert({ - where: { txHash }, - update: {}, - create: { - txHash, - stakerAddress, - tokenAddress, - strategyAddress, - shares, - createdAtBlock, - createdAt - } - }) - ) - } } - await bulkUpdateDbTransactions(dbTransactions) + await bulkUpdateDbTransactions( + dbTransactions, + `[Data] Deposit from: ${firstBlock} to: ${lastBlock} size: ${depositList.length}` + ) // Storing last synced block await saveLastSyncBlock(blockSyncKey, lastBlock) - - console.log('Seeded Deposits:', depositList.length) } From 2115a0ad23657bc28bbc34971565dd9d06951dc2 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 7 Jun 2024 10:54:19 +0530 Subject: [PATCH 41/62] deposit seeding added to index.ts --- packages/seeder/src/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 40a69268..5549b008 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -19,6 +19,8 @@ import { seedQueuedWithdrawals } from './seedWithdrawalsQueued' import { seedCompletedWithdrawals } from './seedWithdrawalsCompleted' import { seedLogsWithdrawalQueued } from './events/seedLogsWithdrawalQueued' import { seedLogsWithdrawalCompleted } from './events/seedLogsWithdrawalCompleted' +import { seedLogsDeposit } from './events/seedLogsDeposit' +import { seedDeposits } from './seedDeposits' console.log('Initializing seeder ...') @@ -42,6 +44,7 @@ async function seedEigenDataLoop() { await seedLogsPodDeployed(targetBlock) await seedLogsWithdrawalQueued(targetBlock) await seedLogsWithdrawalCompleted(targetBlock) + await seedLogsDeposit(targetBlock) await seedAvs() await seedOperators() @@ -50,6 +53,7 @@ async function seedEigenDataLoop() { await seedOperatorShares() await seedQueuedWithdrawals() await seedCompletedWithdrawals() + await seedDeposits() } catch (error) { console.log('Failed to seed data at:', Date.now()) console.log(error) From d1b98c88f98f5fcd00ecb8940521175e894aeed6 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 7 Jun 2024 12:14:55 +0530 Subject: [PATCH 42/62] metadata fetch and updated outsourced to monitors from seeder --- packages/api/.env.example | 3 +- packages/api/src/utils/jwtUtils.ts | 26 +++++ packages/prisma/schema.prisma | 4 + packages/seeder/src/monitors/avsMetadata.ts | 76 +++++++++++++ .../seeder/src/monitors/operatorMetadata.ts | 76 +++++++++++++ packages/seeder/src/seedAvs.ts | 106 +++++++----------- packages/seeder/src/seedOperators.ts | 106 ++++++++---------- packages/seeder/src/utils/seeder.ts | 20 ++++ 8 files changed, 291 insertions(+), 126 deletions(-) create mode 100644 packages/api/src/utils/jwtUtils.ts create mode 100644 packages/seeder/src/monitors/avsMetadata.ts create mode 100644 packages/seeder/src/monitors/operatorMetadata.ts diff --git a/packages/api/.env.example b/packages/api/.env.example index 1b9d3737..f20d3168 100644 --- a/packages/api/.env.example +++ b/packages/api/.env.example @@ -4,4 +4,5 @@ NETWORK_CHAIN_RPC_URL = "" NETWORK_CHAIN_WSS_URL = "" DATABASE_URL = "" DIRECT_URL = "" -CMC_API_KEY = "" \ No newline at end of file +CMC_API_KEY = "" +JWT_SECRET = "" \ No newline at end of file diff --git a/packages/api/src/utils/jwtUtils.ts b/packages/api/src/utils/jwtUtils.ts new file mode 100644 index 00000000..d013c9a0 --- /dev/null +++ b/packages/api/src/utils/jwtUtils.ts @@ -0,0 +1,26 @@ +import 'dotenv/config' +import jwt from 'jsonwebtoken' +import type { Request, Response, NextFunction } from 'express' + +const JWT_SECRET = process.env.JWT_SECRET || '' + +export function authenticateJWT( + req: Request, + res: Response, + next: NextFunction +) { + const token = req.header('Authorization')?.split(' ')[1] + + if (!token) { + return res + .status(401) + .json({ message: 'Access denied. No token provided.' }) + } + + try { + jwt.verify(token, JWT_SECRET) + next() + } catch (error) { + res.status(400).json({ message: 'Invalid token.' }) + } +} \ No newline at end of file diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 24d6f716..5b388f02 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -11,6 +11,7 @@ datasource db { model Avs { address String @id @unique + metadataUrl String metadataName String metadataDescription String metadataDiscord String? @@ -18,6 +19,7 @@ model Avs { metadataTelegram String? metadataWebsite String? metadataX String? + isMetadataSynced Boolean @default(false) operators AvsOperator[] curatedMetadata AvsCuratedMetadata? @@ -65,6 +67,7 @@ model Strategies { model Operator { address String @id @unique + metadataUrl String metadataName String metadataDescription String metadataDiscord String? @@ -72,6 +75,7 @@ model Operator { metadataTelegram String? metadataWebsite String? metadataX String? + isMetadataSynced Boolean @default(false) avs AvsOperator[] shares OperatorStrategyShares[] diff --git a/packages/seeder/src/monitors/avsMetadata.ts b/packages/seeder/src/monitors/avsMetadata.ts new file mode 100644 index 00000000..6fc86f48 --- /dev/null +++ b/packages/seeder/src/monitors/avsMetadata.ts @@ -0,0 +1,76 @@ +import { getPrismaClient } from '../utils/prismaClient' +import type { EntityMetadata } from '../utils/metadata' +import { fetchWithTimeout, bulkUpdateDbTransactions } from '../utils/seeder' +import { isValidMetadataUrl, validateMetadata } from '../utils/metadata' + +export async function monitorAvsMetadata() { + console.log('Monitoring AVS Metadata...') + + const prismaClient = getPrismaClient() + const metadataList: Map = new Map() + + let skip = 0 + const take = 100 + + while (true) { + const avsEntries = await prismaClient.avs.findMany({ + where: { + isMetadataSynced: false + }, + take: take, + skip: skip, + orderBy: { + createdAtBlock: 'asc' + } + }) + + if (avsEntries.length === 0) { + break + } + + for (const record of avsEntries) { + try { + if (record.metadataUrl && isValidMetadataUrl(record.metadataUrl)) { + const response = await fetchWithTimeout(record.metadataUrl) + const data = response ? await response.text() : '' + const avsMetadata = validateMetadata(data) + + if (avsMetadata) { + metadataList.set(record.address, avsMetadata) + } else { + throw new Error('Invalid avs metadata uri') + } + } else { + throw new Error('Invalid avs metadata uri') + } + } catch (error) {} + } + skip += take + } + + // Prepare db transaction object + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + for (const [address, metadata] of metadataList) { + dbTransactions.push( + prismaClient.avs.update({ + where: { address }, + data: { + metadataName: metadata.name, + metadataDescription: metadata.description, + metadataLogo: metadata.logo, + metadataDiscord: metadata.discord, + metadataTelegram: metadata.telegram, + metadataWebsite: metadata.website, + metadataX: metadata.x, + isMetadataSynced: true + } + }) + ) + } + + await bulkUpdateDbTransactions(dbTransactions) + + console.log('Updated AVS metadatas: ', metadataList.size) +} \ No newline at end of file diff --git a/packages/seeder/src/monitors/operatorMetadata.ts b/packages/seeder/src/monitors/operatorMetadata.ts new file mode 100644 index 00000000..40a7884c --- /dev/null +++ b/packages/seeder/src/monitors/operatorMetadata.ts @@ -0,0 +1,76 @@ +import { getPrismaClient } from '../utils/prismaClient' + import type { EntityMetadata } from '../utils/metadata' + import { fetchWithTimeout, bulkUpdateDbTransactions } from '../utils/seeder' + import { isValidMetadataUrl, validateMetadata } from '../utils/metadata' + + export async function monitorOperatorMetadata() { + console.log('Monitoring Operator Metadata...') + + const prismaClient = getPrismaClient() + const metadataList: Map = new Map() + + let skip = 0 + const take = 100 + + while (true) { + const operatorEntries = await prismaClient.operator.findMany({ + where: { + isMetadataSynced: false + }, + take: take, + skip: skip, + orderBy: { + createdAtBlock: 'asc' + } + }) + + if (operatorEntries.length === 0) { + break + } + + for (const record of operatorEntries) { + try { + if (record.metadataUrl && isValidMetadataUrl(record.metadataUrl)) { + const response = await fetchWithTimeout(record.metadataUrl) + const data = response ? await response.text() : '' + const operatorMetadata = validateMetadata(data) + + if (operatorMetadata) { + metadataList.set(record.address, operatorMetadata) + } else { + throw new Error('Invalid operator metadata uri') + } + } else { + throw new Error('Invalid operator metadata uri') + } + } catch (error) {} + } + skip += take + } + + // Prepare db transaction object + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + + for (const [address, metadata] of metadataList) { + dbTransactions.push( + prismaClient.operator.update({ + where: { address }, + data: { + metadataName: metadata.name, + metadataDescription: metadata.description, + metadataLogo: metadata.logo, + metadataDiscord: metadata.discord, + metadataTelegram: metadata.telegram, + metadataWebsite: metadata.website, + metadataX: metadata.x, + isMetadataSynced: true + } + }) + ) + } + + await bulkUpdateDbTransactions(dbTransactions) + + console.log('Updated Operator metadatas: ', metadataList.size) + } \ No newline at end of file diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 62aaaa96..5b282534 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -1,5 +1,4 @@ import type prisma from '@prisma/client' -import { isValidMetadataUrl, validateMetadata } from './utils/metadata' import { type EntityMetadata, defaultMetadata } from './utils/metadata' import { getPrismaClient } from './utils/prismaClient' import { @@ -13,19 +12,15 @@ const blockSyncKey = 'lastSyncedBlock_avs' const blockSyncKeyLogs = 'lastSyncedBlock_logs_avs' interface AvsEntryRecord { + metadataUrl: string metadata: EntityMetadata + isMetadataSynced: boolean createdAtBlock: bigint updatedAtBlock: bigint createdAt: Date updatedAt: Date } -/** - * Utility function to seed avs - * - * @param fromBlock - * @param toBlock - */ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const prismaClient = getPrismaClient() const avsList: Map = new Map() @@ -63,50 +58,29 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const blockNumber = BigInt(log.blockNumber) const timestamp = log.blockTime - try { - if (log.metadataURI && isValidMetadataUrl(log.metadataURI)) { - const response = await fetch(log.metadataURI) - const data = await response.text() - const avsMetadata = validateMetadata(data) - - if (avsMetadata) { - if (existingRecord) { - // Avs already registered, valid metadata uri - avsList.set(avsAddress, { - metadata: avsMetadata, - createdAtBlock: existingRecord.createdAtBlock, - updatedAtBlock: blockNumber, - createdAt: existingRecord.createdAt, - updatedAt: timestamp - }) - } else { - // Avs not registered, valid metadata uri - avsList.set(avsAddress, { - metadata: avsMetadata, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } - } else { - throw new Error('Missing avs metadata') - } - } else { - throw new Error('Invalid avs metadata uri') - } - } catch (error) { - if (!existingRecord) { - // Avs not registered, invalid metadata uri - avsList.set(avsAddress, { - metadata: defaultMetadata, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } // Ignore case where Avs is already registered and is updated with invalid metadata uri - } + if (existingRecord) { + // Avs has been registered before in this fetch + avsList.set(avsAddress, { + metadataUrl: log.metadataURI, + metadata: defaultMetadata, + isMetadataSynced: false, + createdAtBlock: existingRecord.createdAtBlock, + updatedAtBlock: blockNumber, + createdAt: existingRecord.createdAt, + updatedAt: timestamp + }) + } else { + // Avs being registered for the first time in this fetch + avsList.set(avsAddress, { + metadataUrl: log.metadataURI, + metadata: defaultMetadata, + isMetadataSynced: false, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, // Will be omitted in upsert if avs exists in db + updatedAt: timestamp + }) + } } // Prepare db transaction object @@ -120,10 +94,11 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { for (const [ address, - { metadata, createdAtBlock, updatedAtBlock, createdAt, updatedAt } + { metadataUrl, metadata, isMetadataSynced, createdAtBlock, updatedAtBlock, createdAt, updatedAt } ] of avsList) { newAvs.push({ address, + metadataUrl, metadataName: metadata.name, metadataDescription: metadata.description, metadataLogo: metadata.logo, @@ -131,10 +106,11 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, metadataX: metadata.x, - createdAtBlock: createdAtBlock, - updatedAtBlock: updatedAtBlock, - createdAt: createdAt, - updatedAt: updatedAt + isMetadataSynced, + createdAtBlock, + updatedAtBlock, + createdAt, + updatedAt }) } @@ -147,12 +123,13 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { } else { for (const [ address, - { metadata, createdAtBlock, updatedAtBlock, createdAt, updatedAt } + { metadataUrl, metadata, isMetadataSynced, createdAtBlock, updatedAtBlock, createdAt, updatedAt } ] of avsList) { dbTransactions.push( prismaClient.avs.upsert({ where: { address }, update: { + metadataUrl, metadataName: metadata.name, metadataDescription: metadata.description, metadataLogo: metadata.logo, @@ -160,11 +137,13 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, metadataX: metadata.x, - updatedAtBlock: updatedAtBlock, - updatedAt: updatedAt + isMetadataSynced, + updatedAtBlock, + updatedAt }, create: { address, + metadataUrl, metadataName: metadata.name, metadataDescription: metadata.description, metadataLogo: metadata.logo, @@ -172,10 +151,11 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, metadataX: metadata.x, - createdAtBlock: createdAtBlock, - updatedAtBlock: updatedAtBlock, - createdAt: createdAt, - updatedAt: updatedAt + isMetadataSynced, + createdAtBlock, + updatedAtBlock, + createdAt, + updatedAt } }) ) diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index cc95275e..3e0075b7 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -1,11 +1,6 @@ import type prisma from '@prisma/client' +import { type EntityMetadata, defaultMetadata } from './utils/metadata' import { getPrismaClient } from './utils/prismaClient' -import { - type EntityMetadata, - defaultMetadata, - isValidMetadataUrl, - validateMetadata -} from './utils/metadata' import { baseBlock, bulkUpdateDbTransactions, @@ -17,7 +12,9 @@ const blockSyncKey = 'lastSyncedBlock_operators' const blockSyncKeyLogs = 'lastSyncedBlock_logs_operators' interface OperatorEntryRecord { + metadataUrl: string metadata: EntityMetadata + isMetadataSynced: boolean createdAtBlock: bigint updatedAtBlock: bigint createdAt: Date @@ -63,50 +60,29 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const blockNumber = BigInt(log.blockNumber) const timestamp = log.blockTime - try { - if (log.metadataURI && isValidMetadataUrl(log.metadataURI)) { - const response = await fetch(log.metadataURI) - const data = await response.text() - const operatorMetadata = validateMetadata(data) - - if (operatorMetadata) { - if (existingRecord) { - // Operator already registered, valid metadata uri - operatorList.set(operatorAddress, { - metadata: operatorMetadata, - createdAtBlock: existingRecord.createdAtBlock, - updatedAtBlock: blockNumber, - createdAt: existingRecord.createdAt, - updatedAt: timestamp - }) - } else { - // Operator not registered, valid metadata uri - operatorList.set(operatorAddress, { - metadata: operatorMetadata, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } - } else { - throw new Error('Missing operator metadata') - } - } else { - throw new Error('Invalid operator metadata uri') - } - } catch (error) { - if (!existingRecord) { - // Operator not registered, invalid metadata uri - operatorList.set(operatorAddress, { - metadata: defaultMetadata, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } // Ignore case where Operator is already registered and is updated with invalid metadata uri - } + if (existingRecord) { + // Operator has been registered before in this fetch + operatorList.set(operatorAddress, { + metadataUrl: log.metadataURI, + metadata: defaultMetadata, + isMetadataSynced: false, + createdAtBlock: existingRecord.createdAtBlock, + updatedAtBlock: blockNumber, + createdAt: existingRecord.createdAt, + updatedAt: timestamp + }) + } else { + // Operator being registered for the first time in this fetch + operatorList.set(operatorAddress, { + metadataUrl: log.metadataURI, + metadata: defaultMetadata, + isMetadataSynced: false, + createdAtBlock: blockNumber, // Will be omitted in upsert if operator exists in db + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) + } } // Prepare db transaction object @@ -120,10 +96,11 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { for (const [ address, - { metadata, createdAtBlock, updatedAtBlock, createdAt, updatedAt } + { metadataUrl, metadata, isMetadataSynced, createdAtBlock, updatedAtBlock, createdAt, updatedAt } ] of operatorList) { newOperator.push({ address, + metadataUrl, metadataName: metadata.name, metadataDescription: metadata.description, metadataLogo: metadata.logo, @@ -131,10 +108,11 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, metadataX: metadata.x, - createdAtBlock: createdAtBlock, - updatedAtBlock: updatedAtBlock, - createdAt: createdAt, - updatedAt: updatedAt + isMetadataSynced, + createdAtBlock, + updatedAtBlock, + createdAt, + updatedAt }) } @@ -147,12 +125,13 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { } else { for (const [ address, - { metadata, createdAtBlock, updatedAtBlock, createdAt, updatedAt } + { metadataUrl, metadata, isMetadataSynced, createdAtBlock, updatedAtBlock, createdAt, updatedAt } ] of operatorList) { dbTransactions.push( prismaClient.operator.upsert({ where: { address }, update: { + metadataUrl, metadataName: metadata.name, metadataDescription: metadata.description, metadataLogo: metadata.logo, @@ -160,11 +139,13 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, metadataX: metadata.x, - updatedAtBlock: updatedAtBlock, - updatedAt: updatedAt + isMetadataSynced, + updatedAtBlock, + updatedAt }, create: { address, + metadataUrl, metadataName: metadata.name, metadataDescription: metadata.description, metadataLogo: metadata.logo, @@ -172,10 +153,11 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { metadataTelegram: metadata.telegram, metadataWebsite: metadata.website, metadataX: metadata.x, - createdAtBlock: createdAtBlock, - updatedAtBlock: updatedAtBlock, - createdAt: createdAt, - updatedAt: updatedAt + isMetadataSynced, + createdAtBlock, + updatedAtBlock, + createdAt, + updatedAt } }) ) diff --git a/packages/seeder/src/utils/seeder.ts b/packages/seeder/src/utils/seeder.ts index 7c5ce0bd..b1e85074 100644 --- a/packages/seeder/src/utils/seeder.ts +++ b/packages/seeder/src/utils/seeder.ts @@ -97,3 +97,23 @@ export async function getBlockDataFromDb(fromBlock: bigint, toBlock: bigint) { return new Map(blockData.map((block) => [block.number, block.timestamp])) } + +export async function fetchWithTimeout( + url: string, + timeout = 5000 +): Promise { + const controller = new AbortController() + const timeoutId = setTimeout(() => controller.abort(), timeout) + + try { + const response = await fetch(url, { signal: controller.signal }) + return response + } catch (error) { + if (error.name === 'AbortError') { + throw new Error('Request timed out') + } + throw error + } finally { + clearTimeout(timeoutId) + } +} \ No newline at end of file From 96ee9fa3aaed8fd5387de238feb26171558824e9 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 7 Jun 2024 12:18:42 +0530 Subject: [PATCH 43/62] monitors added to index.ts --- packages/seeder/src/index.ts | 16 ++++++++++++++++ packages/seeder/src/monitors/avsMetadata.ts | 2 +- packages/seeder/src/monitors/operatorMetadata.ts | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 40a69268..1e5bcd5d 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -19,6 +19,8 @@ import { seedQueuedWithdrawals } from './seedWithdrawalsQueued' import { seedCompletedWithdrawals } from './seedWithdrawalsCompleted' import { seedLogsWithdrawalQueued } from './events/seedLogsWithdrawalQueued' import { seedLogsWithdrawalCompleted } from './events/seedLogsWithdrawalCompleted' +import { monitorAvsMetadata } from './monitors/avsMetadata' +import { monitorOperatorMetadata } from './monitors/operatorMetadata' console.log('Initializing seeder ...') @@ -77,5 +79,19 @@ async function seedEigenPodValidators() { } } +async function monitorMetadatas() { + while (true) { + try { + await monitorAvsMetadata() + await monitorOperatorMetadata() + } catch (error) { + console.log('Failed to monitor metadatas at: ', Date.now()) + } + + await delay(420) // Wait for 7 minutes (420 seconds) + } +} + seedEigenDataLoop() seedEigenPodValidators() +monitorMetadatas() diff --git a/packages/seeder/src/monitors/avsMetadata.ts b/packages/seeder/src/monitors/avsMetadata.ts index 6fc86f48..7258308f 100644 --- a/packages/seeder/src/monitors/avsMetadata.ts +++ b/packages/seeder/src/monitors/avsMetadata.ts @@ -20,7 +20,7 @@ export async function monitorAvsMetadata() { take: take, skip: skip, orderBy: { - createdAtBlock: 'asc' + createdAtBlock: 'desc' } }) diff --git a/packages/seeder/src/monitors/operatorMetadata.ts b/packages/seeder/src/monitors/operatorMetadata.ts index 40a7884c..e49242bb 100644 --- a/packages/seeder/src/monitors/operatorMetadata.ts +++ b/packages/seeder/src/monitors/operatorMetadata.ts @@ -20,7 +20,7 @@ import { getPrismaClient } from '../utils/prismaClient' take: take, skip: skip, orderBy: { - createdAtBlock: 'asc' + createdAtBlock: 'desc' } }) From 593ebb53875c170c8c777aa12bfb1b2a7102482d Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 7 Jun 2024 13:17:17 +0530 Subject: [PATCH 44/62] added invalidate routes for avs/operators, removed ismetadatasync from api response --- package-lock.json | 4942 +++++++++-------- packages/api/package.json | 1 + packages/api/src/routes/avs/avsController.ts | 38 +- packages/api/src/routes/avs/avsRoutes.ts | 10 + .../routes/operators/operatorController.ts | 40 +- .../src/routes/operators/operatorRoutes.ts | 11 +- packages/api/src/utils/jwtUtils.ts | 2 +- packages/seeder/src/monitors/avsMetadata.ts | 2 +- .../seeder/src/monitors/operatorMetadata.ts | 128 +- packages/seeder/src/seedAvs.ts | 22 +- packages/seeder/src/seedOperators.ts | 22 +- 11 files changed, 2771 insertions(+), 2447 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0ec220b4..22767925 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,2372 +1,2574 @@ { - "name": "eigen-explorer-backend", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "eigen-explorer-backend", - "version": "1.0.0", - "license": "Apache-2.0", - "workspaces": [ - "packages/*" - ], - "dependencies": { - "route-cache": "^0.7.0" - } - }, - "node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "license": "MIT" - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "license": "BSD-3-Clause" - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", - "dev": true - }, - "node_modules/@noble/curves": { - "version": "1.2.0", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.3.2", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@prisma/client": { - "version": "5.11.0", - "hasInstallScript": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.13" - }, - "peerDependencies": { - "prisma": "*" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - } - } - }, - "node_modules/@prisma/debug": { - "version": "5.11.0", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/engines": { - "version": "5.11.0", - "devOptional": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "5.11.0", - "@prisma/engines-version": "5.11.0-15.efd2449663b3d73d637ea1fd226bafbcf45b3102", - "@prisma/fetch-engine": "5.11.0", - "@prisma/get-platform": "5.11.0" - } - }, - "node_modules/@prisma/engines-version": { - "version": "5.11.0-15.efd2449663b3d73d637ea1fd226bafbcf45b3102", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/fetch-engine": { - "version": "5.11.0", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "5.11.0", - "@prisma/engines-version": "5.11.0-15.efd2449663b3d73d637ea1fd226bafbcf45b3102", - "@prisma/get-platform": "5.11.0" - } - }, - "node_modules/@prisma/get-platform": { - "version": "5.11.0", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "5.11.0" - } - }, - "node_modules/@scure/base": { - "version": "1.1.5", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "1.3.2", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.2.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.2.1", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@sideway/address": { - "version": "4.1.5", - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "license": "BSD-3-Clause" - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "license": "BSD-3-Clause" - }, - "node_modules/@slack/logger": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-4.0.0.tgz", - "integrity": "sha512-Wz7QYfPAlG/DR+DfABddUZeNgoeY7d1J39OCR2jR+v7VBsB8ezulDK5szTnDDPDwLH5IWhLvXIHlCFZV7MSKgA==", - "dependencies": { - "@types/node": ">=18.0.0" - }, - "engines": { - "node": ">= 18", - "npm": ">= 8.6.0" - } - }, - "node_modules/@slack/types": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@slack/types/-/types-2.11.0.tgz", - "integrity": "sha512-UlIrDWvuLaDly3QZhCPnwUSI/KYmV1N9LyhuH6EDKCRS1HWZhyTG3Ja46T3D0rYfqdltKYFXbJSSRPwZpwO0cQ==", - "engines": { - "node": ">= 12.13.0", - "npm": ">= 6.12.0" - } - }, - "node_modules/@slack/web-api": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-7.0.4.tgz", - "integrity": "sha512-21tbte7N8itwjG7nsiQbDmXP9T/oqEILuvyL2UtgaZxfSY4a1JWWsLGL5n/hcgS2WE2oxmEHsBuhuRkZDwDovw==", - "dependencies": { - "@slack/logger": "^4.0.0", - "@slack/types": "^2.9.0", - "@types/node": ">=18.0.0", - "@types/retry": "0.12.0", - "axios": "^1.6.5", - "eventemitter3": "^5.0.1", - "form-data": "^4.0.0", - "is-electron": "2.2.2", - "is-stream": "^2", - "p-queue": "^6", - "p-retry": "^4", - "retry": "^0.13.1" - }, - "engines": { - "node": ">= 18", - "npm": ">= 8.6.0" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cookie-parser": { - "version": "1.4.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/express": { - "version": "4.17.21", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.43", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-QjCOmf5kYwekcsfEKhcEHMK8/SvgnneuSDXFERBuC/DPca2KJIO/gpChTsVb35BoWLBpEAJWz1GFVEArSdtKtw==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/morgan": { - "version": "1.9.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ms": { - "version": "0.7.34", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.12.2", - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/qs": { - "version": "6.9.14", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" - }, - "node_modules/@types/route-cache": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@types/route-cache/-/route-cache-0.5.5.tgz", - "integrity": "sha512-HJYRyjX10iV8u9mhl1oiDX5SLm8ldJuFeRWyi0FoeOoX7aVa3L7XHLVm+p+D5i9PCnNElIbbjU6tfM4+eHshyA==", - "dev": true, - "dependencies": { - "@types/express": "*", - "@types/lru-cache": "^4.1.3", - "@types/node": "*", - "ioredis": "^5.3.2" - } - }, - "node_modules/@types/send": { - "version": "0.17.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/abitype": { - "version": "1.0.0", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/axios": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", - "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/basic-auth": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/basic-auth/node_modules/safe-buffer": { - "version": "5.1.2", - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/body-parser": { - "version": "1.20.2", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/depd": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/http-errors": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/http-errors/node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "node_modules/body-parser/node_modules/http-errors/node_modules/setprototypeof": { - "version": "1.2.0", - "license": "ISC" - }, - "node_modules/body-parser/node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/on-finished": { - "version": "2.4.1", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/character-parser": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.4.1", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-parser": { - "version": "1.4.6", - "license": "MIT", - "dependencies": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/dotenv": { - "version": "16.4.5", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/eigen-explorer-backend": { - "resolved": "packages/api", - "link": true - }, - "node_modules/eigen-explorer-backend-db": { - "resolved": "packages/prisma", - "link": true - }, - "node_modules/eigen-explorer-backend-monitor": { - "resolved": "packages/monitor", - "link": true - }, - "node_modules/eigen-explorer-backend-seeder": { - "resolved": "packages/seeder", - "link": true - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.19.12", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, - "node_modules/express": { - "version": "4.19.2", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/cookie": { - "version": "0.6.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/depd": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/http-errors": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/http-errors/node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "node_modules/express/node_modules/on-finished": { - "version": "2.4.1", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/setprototypeof": { - "version": "1.2.0", - "license": "ISC" - }, - "node_modules/express/node_modules/statuses": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/on-finished": { - "version": "2.4.1", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/statuses": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.7.3", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/helmet": { - "version": "7.1.0", - "license": "MIT", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/http-errors": { - "version": "1.6.3", - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-errors/node_modules/depd": { - "version": "1.1.2", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-errors/node_modules/setprototypeof": { - "version": "1.1.0", - "license": "ISC" - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "1.4.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, - "node_modules/inherits": { - "version": "2.0.3", - "license": "ISC" - }, - "node_modules/ioredis": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", - "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==", - "dev": true, - "dependencies": { - "@ioredis/commands": "^1.1.1", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" - }, - "engines": { - "node": ">=12.22.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ioredis" - } - }, - "node_modules/ioredis/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/ioredis/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-electron": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", - "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-promise": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isows": { - "version": "1.0.3", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" - } - ], - "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/jade": { - "version": "0.29.0", - "dependencies": { - "character-parser": "~1.0.0", - "commander": "0.6.1", - "mkdirp": "0.3.x", - "monocle": "~0.1.43", - "transformers": "~1.8.0" - }, - "bin": { - "jade": "bin/jade" - } - }, - "node_modules/jade/node_modules/commander": { - "version": "0.6.1", - "engines": { - "node": ">= 0.4.x" - } - }, - "node_modules/joi": { - "version": "17.12.2", - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^9.3.0", - "@hapi/topo": "^5.1.0", - "@sideway/address": "^4.1.5", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "dev": true - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/methods": { - "version": "1.1.2", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mkdirp": { - "version": "0.3.5", - "license": "MIT" - }, - "node_modules/monocle": { - "version": "0.1.48", - "license": "BSD", - "dependencies": { - "readdirp": "~0.2.3" - } - }, - "node_modules/monocle/node_modules/readdirp": { - "version": "0.2.5", - "license": "MIT", - "dependencies": { - "minimatch": ">=0.2.4" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/morgan": { - "version": "1.9.1", - "license": "MIT", - "dependencies": { - "basic-auth": "~2.0.0", - "debug": "2.6.9", - "depd": "~1.1.2", - "on-finished": "~2.3.0", - "on-headers": "~1.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/morgan/node_modules/depd": { - "version": "1.1.2", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/morgan/node_modules/on-finished": { - "version": "2.3.0", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/nodemon": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", - "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^4", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^7.5.3", - "simple-update-notifier": "^2.0.0", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/nodemon/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/openapi": { - "resolved": "packages/openapi", - "link": true - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-queue": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", - "dependencies": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-queue/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "license": "MIT" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prisma": { - "version": "5.11.0", - "devOptional": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/engines": "5.11.0" - }, - "bin": { - "prisma": "build/index.js" - }, - "engines": { - "node": ">=16.13" - } - }, - "node_modules/promise": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "is-promise": "~1" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "node_modules/qs": { - "version": "6.11.0", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/http-errors": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/http-errors/node_modules/depd": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/http-errors/node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "node_modules/raw-body/node_modules/http-errors/node_modules/setprototypeof": { - "version": "1.2.0", - "license": "ISC" - }, - "node_modules/raw-body/node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", - "dev": true, - "dependencies": { - "redis-errors": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/route-cache": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/route-cache/-/route-cache-0.7.0.tgz", - "integrity": "sha512-M4LbH7fTVwH72+CDSv1eaeC+0JWjo427Zp7nmn4LXf31OaaRhvK2xMNTHZgVT8caLDXrzREPHW2QPzKN/ZMmEg==", - "dependencies": { - "debug": "3.1.0", - "lru-cache": "4.0.1" - } - }, - "node_modules/route-cache/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/route-cache/node_modules/lru-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz", - "integrity": "sha512-MX0ZnRoVTWXBiNe9dysqKXjvhmQgHsOirh/2rerIVJ8sbQeMxc5OPj0HDpVV3bYjdE6GTHrPf8BEHJqWHFkjHA==", - "dependencies": { - "pseudomap": "^1.0.1", - "yallist": "^2.0.0" - } - }, - "node_modules/route-cache/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.18.0", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/depd": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/http-errors": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/http-errors/node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "node_modules/send/node_modules/http-errors/node_modules/setprototypeof": { - "version": "1.2.0", - "license": "ISC" - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "license": "MIT" - }, - "node_modules/send/node_modules/on-finished": { - "version": "2.4.1", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static": { - "version": "1.15.0", - "license": "MIT", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/standard-as-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", - "dev": true - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "dependencies": { - "nopt": "~1.0.10" - }, - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/transformers": { - "version": "1.8.3", - "license": "MIT", - "dependencies": { - "promise": "~2.0" - } - }, - "node_modules/tsx": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.3.tgz", - "integrity": "sha512-+fQnMqIp/jxZEXLcj6WzYy9FhcS5/Dfk8y4AtzJ6ejKcKqmfTF8Gso/jtrzDggCF2zTU20gJa6n8XqPYwDAUYQ==", - "dev": true, - "dependencies": { - "esbuild": "~0.19.10", - "get-tsconfig": "^4.7.2" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "devOptional": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, - "node_modules/undici-types": { - "version": "5.26.5", - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/viem": { - "version": "2.9.21", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.9.21.tgz", - "integrity": "sha512-8GtxPjPGpiN5cmr19zSX9mb1LX/eON3MPxxAd3QmyUFn69Rp566zlREOqE7zM35y5yX59fXwnz6O3X7e9+C9zg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@scure/bip32": "1.3.2", - "@scure/bip39": "1.2.1", - "abitype": "1.0.0", - "isows": "1.0.3", - "ws": "8.13.0" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/ws": { - "version": "8.13.0", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/zod": { - "version": "3.23.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.4.tgz", - "integrity": "sha512-/AtWOKbBgjzEYYQRNfoGKHObgfAZag6qUJX1VbHo2PRBgS+wfWagEY2mizjfyAPcGesrJOcx/wcl0L9WnVrHFw==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-error": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/zod-error/-/zod-error-1.5.0.tgz", - "integrity": "sha512-zzopKZ/skI9iXpqCEPj+iLCKl9b88E43ehcU+sbRoHuwGd9F1IDVGQ70TyO6kmfiRL1g4IXkjsXK+g1gLYl4WQ==", - "dependencies": { - "zod": "^3.20.2" - } - }, - "node_modules/zod-openapi": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/zod-openapi/-/zod-openapi-2.17.0.tgz", - "integrity": "sha512-S6x14LmPWZ3Sbnx71pqzIB6oIox1ce6vHnJY7ZUYLBm8TTEQ6/g6+kwutna5jplAhzphkMbYPbtW3cmHXFcRBg==", - "engines": { - "node": ">=16.11" - }, - "peerDependencies": { - "zod": "^3.21.4" - } - }, - "packages/api": { - "name": "eigen-explorer-backend", - "version": "0.0.1", - "dependencies": { - "@prisma/client": "^5.11.0", - "cookie-parser": "~1.4.4", - "cors": "^2.8.5", - "debug": "~2.6.9", - "dotenv": "^16.4.5", - "express": "^4.18.3", - "helmet": "^7.1.0", - "http-errors": "~1.6.3", - "jade": "^0.29.0", - "joi": "^17.12.2", - "morgan": "~1.9.1", - "route-cache": "^0.7.0", - "viem": "^2.8.14", - "zod": "^3.23.4", - "zod-error": "^1.5.0", - "zod-openapi": "^2.17.0" - }, - "devDependencies": { - "@types/cookie-parser": "^1.4.7", - "@types/cors": "^2.8.17", - "@types/debug": "^4.1.12", - "@types/express": "^4.17.21", - "@types/morgan": "^1.9.9", - "@types/node": "^20.12.2", - "@types/route-cache": "^0.5.5", - "prisma": "^5.11.0", - "tsx": "^4.7.1", - "typescript": "^5.4.3" - } - }, - "packages/docs": { - "name": "eigen-explorer-backend-docs", - "version": "0.0.1", - "extraneous": true, - "devDependencies": { - "@types/node": "^20.12.2", - "@types/swagger-jsdoc": "^6.0.4", - "swagger-jsdoc": "^6.2.8", - "tsx": "^4.7.1", - "typescript": "^5.4.3" - } - }, - "packages/monitor": { - "name": "eigen-explorer-backend-monitor", - "version": "0.0.1", - "dependencies": { - "@slack/web-api": "^7.0.4", - "dotenv": "^16.4.5", - "viem": "^2.9.21" - }, - "devDependencies": { - "@types/node": "^20.12.2", - "prisma": "^5.11.0", - "tsx": "^4.7.1", - "typescript": "^5.4.5" - } - }, - "packages/monitoring": { - "name": "eigen-explorer-backend-monitoring", - "version": "0.0.1", - "extraneous": true, - "dependencies": { - "@slack/web-api": "^7.0.4", - "dotenv": "^16.4.5", - "viem": "^2.9.21" - }, - "devDependencies": { - "@types/node": "^20.12.2", - "prisma": "^5.11.0", - "tsx": "^4.7.1", - "typescript": "^5.4.5" - } - }, - "packages/openapi": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "zod": "^3.23.4", - "zod-openapi": "^2.17.0" - }, - "devDependencies": { - "nodemon": "^3.1.0", - "tsx": "^4.7.3", - "typescript": "^5.4.5" - } - }, - "packages/openapi-deprecated": { - "name": "eigen-explorer-backend-docs", - "version": "0.0.1", - "extraneous": true, - "dependencies": { - "zod-openapi": "^2.17.0" - }, - "devDependencies": { - "@types/node": "^20.12.2", - "@types/swagger-jsdoc": "^6.0.4", - "swagger-jsdoc": "^6.2.8", - "tsx": "^4.7.3", - "typescript": "^5.4.3" - } - }, - "packages/prisma": { - "name": "eigen-explorer-backend-db", - "version": "0.0.1", - "devDependencies": { - "prisma": "^5.11.0" - } - }, - "packages/seeder": { - "name": "eigen-explorer-backend-seeder", - "version": "0.0.1", - "dependencies": { - "dotenv": "^16.4.5", - "viem": "^2.9.21" - }, - "devDependencies": { - "@types/node": "^20.12.2", - "prisma": "^5.11.0", - "tsx": "^4.7.1", - "typescript": "^5.4.3" - } - } - } + "name": "eigen-explorer-backend", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "eigen-explorer-backend", + "version": "1.0.0", + "license": "Apache-2.0", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "route-cache": "^0.7.0" + }, + "devDependencies": { + "@biomejs/biome": "1.4.1" + } + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.0", + "license": "MIT" + }, + "node_modules/@biomejs/biome": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.4.1.tgz", + "integrity": "sha512-JccVAwPbhi37pdxbAGmaOBjUTKEwEjWAhl7rKkVVuXHo4MLASXJ5HR8BTgrImi4/7rTBsGz1tgVD1Kwv1CHGRg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.4.1", + "@biomejs/cli-darwin-x64": "1.4.1", + "@biomejs/cli-linux-arm64": "1.4.1", + "@biomejs/cli-linux-x64": "1.4.1", + "@biomejs/cli-win32-arm64": "1.4.1", + "@biomejs/cli-win32-x64": "1.4.1" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.4.1.tgz", + "integrity": "sha512-PZWy2Idndqux38p6AXSDQM2ldRAWi32bvb7bMbTN0ALzpWYMYnxd71ornatumSSJYoNhKmxzDLq+jct7nZJ79w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.4.1.tgz", + "integrity": "sha512-soj3BWhnsM1M2JlzR09cibUzG1owJqetwj/Oo7yg0foijo9lNH9XWXZfJBYDKgW/6Fomn+CC2EcUS+hisQzt9g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.4.1.tgz", + "integrity": "sha512-YIZqfJUg4F+fPsBTXxgD7EU2E5OAYbmYSl/snf4PevwfQCWE/omOFZv+NnIQmjYj9I7ParDgcJvanoA3/kO0JQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.4.1.tgz", + "integrity": "sha512-9YOZw3qBd/KUj63A6Hn2zZgzGb2nbESM0qNmeMXgmqinVKM//uc4OgY5TuKITuGjMSvcVxxd4dX1IzYjV9qvNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.4.1.tgz", + "integrity": "sha512-nWQbvkNKxYn/kCQ0yVF8kCaS3VzaGvtFSmItXiMknU4521LDjJ7tNWH12Gol+pIslrCbd4E1LhJa0a3ThRsBVg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.4.1.tgz", + "integrity": "sha512-88fR2CQxQ4YLs2BUDuywWYQpUKgU3A3sTezANFc/4LGKQFFLV2yX+F7QAdZVkMHfA+RD9Xg178HomM/6mnTNPA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", + "dev": true + }, + "node_modules/@noble/curves": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.2", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@prisma/client": { + "version": "5.11.0", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "5.11.0", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "5.11.0", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.11.0", + "@prisma/engines-version": "5.11.0-15.efd2449663b3d73d637ea1fd226bafbcf45b3102", + "@prisma/fetch-engine": "5.11.0", + "@prisma/get-platform": "5.11.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "5.11.0-15.efd2449663b3d73d637ea1fd226bafbcf45b3102", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.11.0", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.11.0", + "@prisma/engines-version": "5.11.0-15.efd2449663b3d73d637ea1fd226bafbcf45b3102", + "@prisma/get-platform": "5.11.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "5.11.0", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.11.0" + } + }, + "node_modules/@scure/base": { + "version": "1.1.5", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.2.1", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "license": "BSD-3-Clause" + }, + "node_modules/@slack/logger": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-4.0.0.tgz", + "integrity": "sha512-Wz7QYfPAlG/DR+DfABddUZeNgoeY7d1J39OCR2jR+v7VBsB8ezulDK5szTnDDPDwLH5IWhLvXIHlCFZV7MSKgA==", + "dependencies": { + "@types/node": ">=18.0.0" + }, + "engines": { + "node": ">= 18", + "npm": ">= 8.6.0" + } + }, + "node_modules/@slack/types": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@slack/types/-/types-2.11.0.tgz", + "integrity": "sha512-UlIrDWvuLaDly3QZhCPnwUSI/KYmV1N9LyhuH6EDKCRS1HWZhyTG3Ja46T3D0rYfqdltKYFXbJSSRPwZpwO0cQ==", + "engines": { + "node": ">= 12.13.0", + "npm": ">= 6.12.0" + } + }, + "node_modules/@slack/web-api": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-7.0.4.tgz", + "integrity": "sha512-21tbte7N8itwjG7nsiQbDmXP9T/oqEILuvyL2UtgaZxfSY4a1JWWsLGL5n/hcgS2WE2oxmEHsBuhuRkZDwDovw==", + "dependencies": { + "@slack/logger": "^4.0.0", + "@slack/types": "^2.9.0", + "@types/node": ">=18.0.0", + "@types/retry": "0.12.0", + "axios": "^1.6.5", + "eventemitter3": "^5.0.1", + "form-data": "^4.0.0", + "is-electron": "2.2.2", + "is-stream": "^2", + "p-queue": "^6", + "p-retry": "^4", + "retry": "^0.13.1" + }, + "engines": { + "node": ">= 18", + "npm": ">= 8.6.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.43", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-QjCOmf5kYwekcsfEKhcEHMK8/SvgnneuSDXFERBuC/DPca2KJIO/gpChTsVb35BoWLBpEAJWz1GFVEArSdtKtw==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/morgan": { + "version": "1.9.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.12.2", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/qs": { + "version": "6.9.14", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "node_modules/@types/route-cache": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@types/route-cache/-/route-cache-0.5.5.tgz", + "integrity": "sha512-HJYRyjX10iV8u9mhl1oiDX5SLm8ldJuFeRWyi0FoeOoX7aVa3L7XHLVm+p+D5i9PCnNElIbbjU6tfM4+eHshyA==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/lru-cache": "^4.1.3", + "@types/node": "*", + "ioredis": "^5.3.2" + } + }, + "node_modules/@types/send": { + "version": "0.17.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/abitype": { + "version": "1.0.0", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.22.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/depd": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/http-errors/node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/body-parser/node_modules/http-errors/node_modules/setprototypeof": { + "version": "1.2.0", + "license": "ISC" + }, + "node_modules/body-parser/node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/on-finished": { + "version": "2.4.1", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/character-parser": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "license": "MIT", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/eigen-explorer-backend": { + "resolved": "packages/api", + "link": true + }, + "node_modules/eigen-explorer-backend-db": { + "resolved": "packages/prisma", + "link": true + }, + "node_modules/eigen-explorer-backend-monitor": { + "resolved": "packages/monitor", + "link": true + }, + "node_modules/eigen-explorer-backend-seeder": { + "resolved": "packages/seeder", + "link": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.19.12", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/express": { + "version": "4.19.2", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.6.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/depd": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/http-errors": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/http-errors/node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/express/node_modules/on-finished": { + "version": "2.4.1", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/setprototypeof": { + "version": "1.2.0", + "license": "ISC" + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.4.1", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/statuses": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.3", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/helmet": { + "version": "7.1.0", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/http-errors": { + "version": "1.6.3", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/setprototypeof": { + "version": "1.1.0", + "license": "ISC" + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "1.4.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/inherits": { + "version": "2.0.3", + "license": "ISC" + }, + "node_modules/ioredis": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", + "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==", + "dev": true, + "dependencies": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, + "node_modules/ioredis/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/ioredis/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-electron": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", + "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isows": { + "version": "1.0.3", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wagmi-dev" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/jade": { + "version": "0.29.0", + "dependencies": { + "character-parser": "~1.0.0", + "commander": "0.6.1", + "mkdirp": "0.3.x", + "monocle": "~0.1.43", + "transformers": "~1.8.0" + }, + "bin": { + "jade": "bin/jade" + } + }, + "node_modules/jade/node_modules/commander": { + "version": "0.6.1", + "engines": { + "node": ">= 0.4.x" + } + }, + "node_modules/joi": { + "version": "17.12.2", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "dev": true + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mkdirp": { + "version": "0.3.5", + "license": "MIT" + }, + "node_modules/monocle": { + "version": "0.1.48", + "license": "BSD", + "dependencies": { + "readdirp": "~0.2.3" + } + }, + "node_modules/monocle/node_modules/readdirp": { + "version": "0.2.5", + "license": "MIT", + "dependencies": { + "minimatch": ">=0.2.4" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/morgan": { + "version": "1.9.1", + "license": "MIT", + "dependencies": { + "basic-auth": "~2.0.0", + "debug": "2.6.9", + "depd": "~1.1.2", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/depd": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemon": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", + "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/openapi": { + "resolved": "packages/openapi", + "link": true + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prisma": { + "version": "5.11.0", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/engines": "5.11.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/promise": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "is-promise": "~1" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/qs": { + "version": "6.11.0", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/http-errors/node_modules/depd": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/http-errors/node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/raw-body/node_modules/http-errors/node_modules/setprototypeof": { + "version": "1.2.0", + "license": "ISC" + }, + "node_modules/raw-body/node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dev": true, + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/route-cache": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/route-cache/-/route-cache-0.7.0.tgz", + "integrity": "sha512-M4LbH7fTVwH72+CDSv1eaeC+0JWjo427Zp7nmn4LXf31OaaRhvK2xMNTHZgVT8caLDXrzREPHW2QPzKN/ZMmEg==", + "dependencies": { + "debug": "3.1.0", + "lru-cache": "4.0.1" + } + }, + "node_modules/route-cache/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/route-cache/node_modules/lru-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz", + "integrity": "sha512-MX0ZnRoVTWXBiNe9dysqKXjvhmQgHsOirh/2rerIVJ8sbQeMxc5OPj0HDpVV3bYjdE6GTHrPf8BEHJqWHFkjHA==", + "dependencies": { + "pseudomap": "^1.0.1", + "yallist": "^2.0.0" + } + }, + "node_modules/route-cache/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/depd": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/http-errors": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/http-errors/node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/send/node_modules/http-errors/node_modules/setprototypeof": { + "version": "1.2.0", + "license": "ISC" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "license": "MIT", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "dev": true + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/transformers": { + "version": "1.8.3", + "license": "MIT", + "dependencies": { + "promise": "~2.0" + } + }, + "node_modules/tsx": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.3.tgz", + "integrity": "sha512-+fQnMqIp/jxZEXLcj6WzYy9FhcS5/Dfk8y4AtzJ6ejKcKqmfTF8Gso/jtrzDggCF2zTU20gJa6n8XqPYwDAUYQ==", + "dev": true, + "dependencies": { + "esbuild": "~0.19.10", + "get-tsconfig": "^4.7.2" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/undici-types": { + "version": "5.26.5", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/viem": { + "version": "2.9.21", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.9.21.tgz", + "integrity": "sha512-8GtxPjPGpiN5cmr19zSX9mb1LX/eON3MPxxAd3QmyUFn69Rp566zlREOqE7zM35y5yX59fXwnz6O3X7e9+C9zg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.0", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@scure/bip32": "1.3.2", + "@scure/bip39": "1.2.1", + "abitype": "1.0.0", + "isows": "1.0.3", + "ws": "8.13.0" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ws": { + "version": "8.13.0", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/zod": { + "version": "3.23.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.4.tgz", + "integrity": "sha512-/AtWOKbBgjzEYYQRNfoGKHObgfAZag6qUJX1VbHo2PRBgS+wfWagEY2mizjfyAPcGesrJOcx/wcl0L9WnVrHFw==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-error": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/zod-error/-/zod-error-1.5.0.tgz", + "integrity": "sha512-zzopKZ/skI9iXpqCEPj+iLCKl9b88E43ehcU+sbRoHuwGd9F1IDVGQ70TyO6kmfiRL1g4IXkjsXK+g1gLYl4WQ==", + "dependencies": { + "zod": "^3.20.2" + } + }, + "node_modules/zod-openapi": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/zod-openapi/-/zod-openapi-2.17.0.tgz", + "integrity": "sha512-S6x14LmPWZ3Sbnx71pqzIB6oIox1ce6vHnJY7ZUYLBm8TTEQ6/g6+kwutna5jplAhzphkMbYPbtW3cmHXFcRBg==", + "engines": { + "node": ">=16.11" + }, + "peerDependencies": { + "zod": "^3.21.4" + } + }, + "packages/api": { + "name": "eigen-explorer-backend", + "version": "0.0.1", + "dependencies": { + "@prisma/client": "^5.11.0", + "cookie-parser": "~1.4.4", + "cors": "^2.8.5", + "debug": "~2.6.9", + "dotenv": "^16.4.5", + "express": "^4.18.3", + "helmet": "^7.1.0", + "http-errors": "~1.6.3", + "jade": "^0.29.0", + "joi": "^17.12.2", + "jsonwebtoken": "^9.0.2", + "morgan": "~1.9.1", + "route-cache": "^0.7.0", + "viem": "^2.8.14", + "zod": "^3.23.4", + "zod-error": "^1.5.0", + "zod-openapi": "^2.17.0" + }, + "devDependencies": { + "@types/cookie-parser": "^1.4.7", + "@types/cors": "^2.8.17", + "@types/debug": "^4.1.12", + "@types/express": "^4.17.21", + "@types/morgan": "^1.9.9", + "@types/node": "^20.12.2", + "@types/route-cache": "^0.5.5", + "prisma": "^5.11.0", + "tsx": "^4.7.1", + "typescript": "^5.4.3" + } + }, + "packages/docs": { + "name": "eigen-explorer-backend-docs", + "version": "0.0.1", + "extraneous": true, + "devDependencies": { + "@types/node": "^20.12.2", + "@types/swagger-jsdoc": "^6.0.4", + "swagger-jsdoc": "^6.2.8", + "tsx": "^4.7.1", + "typescript": "^5.4.3" + } + }, + "packages/monitor": { + "name": "eigen-explorer-backend-monitor", + "version": "0.0.1", + "dependencies": { + "@slack/web-api": "^7.0.4", + "dotenv": "^16.4.5", + "viem": "^2.9.21" + }, + "devDependencies": { + "@types/node": "^20.12.2", + "prisma": "^5.11.0", + "tsx": "^4.7.1", + "typescript": "^5.4.5" + } + }, + "packages/monitoring": { + "name": "eigen-explorer-backend-monitoring", + "version": "0.0.1", + "extraneous": true, + "dependencies": { + "@slack/web-api": "^7.0.4", + "dotenv": "^16.4.5", + "viem": "^2.9.21" + }, + "devDependencies": { + "@types/node": "^20.12.2", + "prisma": "^5.11.0", + "tsx": "^4.7.1", + "typescript": "^5.4.5" + } + }, + "packages/openapi": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "zod": "^3.23.4", + "zod-openapi": "^2.17.0" + }, + "devDependencies": { + "nodemon": "^3.1.0", + "tsx": "^4.7.3", + "typescript": "^5.4.5" + } + }, + "packages/openapi-deprecated": { + "name": "eigen-explorer-backend-docs", + "version": "0.0.1", + "extraneous": true, + "dependencies": { + "zod-openapi": "^2.17.0" + }, + "devDependencies": { + "@types/node": "^20.12.2", + "@types/swagger-jsdoc": "^6.0.4", + "swagger-jsdoc": "^6.2.8", + "tsx": "^4.7.3", + "typescript": "^5.4.3" + } + }, + "packages/prisma": { + "name": "eigen-explorer-backend-db", + "version": "0.0.1", + "devDependencies": { + "prisma": "^5.11.0" + } + }, + "packages/seeder": { + "name": "eigen-explorer-backend-seeder", + "version": "0.0.1", + "dependencies": { + "dotenv": "^16.4.5", + "viem": "^2.9.21" + }, + "devDependencies": { + "@types/node": "^20.12.2", + "prisma": "^5.11.0", + "tsx": "^4.7.1", + "typescript": "^5.4.3" + } + } + } } diff --git a/packages/api/package.json b/packages/api/package.json index d8ba759c..31c74b09 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -20,6 +20,7 @@ "http-errors": "~1.6.3", "jade": "^0.29.0", "joi": "^17.12.2", + "jsonwebtoken": "^9.0.2", "morgan": "~1.9.1", "route-cache": "^0.7.0", "viem": "^2.8.14", diff --git a/packages/api/src/routes/avs/avsController.ts b/packages/api/src/routes/avs/avsController.ts index 15773702..e0b4b2a1 100644 --- a/packages/api/src/routes/avs/avsController.ts +++ b/packages/api/src/routes/avs/avsController.ts @@ -59,7 +59,7 @@ export async function getAllAVS(req: Request, res: Response) { : [] const data = await Promise.all( - avsRecords.map(async (avs) => { + avsRecords.map(async ({ isMetadataSynced, ...avs }) => { const restakeableStrategies = await getRestakeableStrategies( avs.address ) @@ -81,6 +81,8 @@ export async function getAllAVS(req: Request, res: Response) { return { ...withCuratedMetadata(avs), + createdAtBlock: avs.createdAtBlock.toString(), + updatedAtBlock: avs.updatedAtBlock.toString(), shares, totalOperators, totalStakers, @@ -175,7 +177,7 @@ export async function getAVS(req: Request, res: Response) { const { address } = req.params const { withTvl } = req.query - const avs = await prisma.avs.findUniqueOrThrow({ + const { isMetadataSynced, ...avs } = await prisma.avs.findUniqueOrThrow({ where: { address: address.toLowerCase(), ...getAvsFilterQuery() }, include: { curatedMetadata: true, @@ -213,6 +215,8 @@ export async function getAVS(req: Request, res: Response) { res.send({ ...withCuratedMetadata(avs), + createdAtBlock: avs.createdAtBlock.toString(), + updatedAtBlock: avs.updatedAtBlock.toString(), shares, totalOperators, totalStakers, @@ -414,6 +418,36 @@ function withOperatorShares(avsOperators) { })) } +/** + * Protected route to invalidate the metadata of a given address + * + * @param req + * @param res + */ +export async function invalidateMetadata(req: Request, res: Response) { + const paramCheck = EthereumAddressSchema.safeParse(req.params.address) + if (!paramCheck.success) { + return handleAndReturnErrorResponse(req, res, paramCheck.error) + } + + try { + const { address } = req.params + + const updateResult = await prisma.avs.updateMany({ + where: { address: address.toLowerCase() }, + data: { isMetadataSynced: false } + }) + + if (updateResult.count === 0) { + throw new Error('Address not found.') + } + + res.send({ message: 'Metadata invalidated successfully.' }) + } catch (error) { + handleAndReturnErrorResponse(req, res, error) + } +} + // Helper functions function withCuratedMetadata(avs): Avs { // Replace metadata with curated metadata diff --git a/packages/api/src/routes/avs/avsRoutes.ts b/packages/api/src/routes/avs/avsRoutes.ts index 76674f16..21d0752b 100644 --- a/packages/api/src/routes/avs/avsRoutes.ts +++ b/packages/api/src/routes/avs/avsRoutes.ts @@ -5,7 +5,9 @@ import { getAVS, getAVSOperators, getAVSStakers, + invalidateMetadata } from './avsController'; +import { authenticateJWT } from '../../utils/jwtUtils' import routeCache from "route-cache"; @@ -22,4 +24,12 @@ router.get('/:address/stakers', routeCache.cacheSeconds(120), getAVSStakers); router.get('/:address/operators', routeCache.cacheSeconds(120), getAVSOperators); +// Protected routes +router.get( + '/:address/invalidate-metadata', + authenticateJWT, + routeCache.cacheSeconds(120), + invalidateMetadata +); + export default router; diff --git a/packages/api/src/routes/operators/operatorController.ts b/packages/api/src/routes/operators/operatorController.ts index 2a961ba3..3eb1e218 100644 --- a/packages/api/src/routes/operators/operatorController.ts +++ b/packages/api/src/routes/operators/operatorController.ts @@ -1,6 +1,7 @@ import type { Request, Response } from 'express' import prisma from '../../utils/prismaClient' import { PaginationQuerySchema } from '../../schema/zod/schemas/paginationQuery' +import { EthereumAddressSchema } from '../../schema/zod/schemas/base/ethereumAddress' import { WithTvlQuerySchema } from '../../schema/zod/schemas/withTvlQuery' import { handleAndReturnErrorResponse } from '../../schema/errors' import { @@ -44,8 +45,10 @@ export async function getAllOperators(req: Request, res: Response) { ? await getStrategiesWithShareUnderlying() : [] - const operators = operatorRecords.map((operator) => ({ + const operators = operatorRecords.map(({ isMetadataSynced, ...operator }) => ({ ...operator, + createdAtBlock: operator.createdAtBlock.toString(), + updatedAtBlock: operator.updatedAtBlock.toString(), totalStakers: operator.stakers.length, tvl: withTvl ? sharesToTVL( @@ -87,7 +90,7 @@ export async function getOperator(req: Request, res: Response) { try { const { address } = req.params - const operator = await prisma.operator.findUniqueOrThrow({ + const { isMetadataSynced, ...operator } = await prisma.operator.findUniqueOrThrow({ where: { address: address.toLowerCase() }, include: { shares: { @@ -102,8 +105,11 @@ export async function getOperator(req: Request, res: Response) { ? await getStrategiesWithShareUnderlying() : [] + res.send({ ...operator, + createdAtBlock: operator.createdAtBlock.toString(), + updatedAtBlock: operator.updatedAtBlock.toString(), totalStakers: operator.stakers.length, tvl: withTvl ? sharesToTVL( @@ -118,3 +124,33 @@ export async function getOperator(req: Request, res: Response) { handleAndReturnErrorResponse(req, res, error) } } + +/** + * Protected route to invalidate the metadata of a given address + * + * @param req + * @param res + */ +export async function invalidateMetadata(req: Request, res: Response) { + const paramCheck = EthereumAddressSchema.safeParse(req.params.address) + if (!paramCheck.success) { + return handleAndReturnErrorResponse(req, res, paramCheck.error) + } + + try { + const { address } = req.params + + const updateResult = await prisma.operator.updateMany({ + where: { address: address.toLowerCase() }, + data: { isMetadataSynced: false } + }) + + if (updateResult.count === 0) { + throw new Error('Address not found.') + } + + res.send({ message: 'Metadata invalidated successfully.' }) + } catch (error) { + handleAndReturnErrorResponse(req, res, error) + } +} diff --git a/packages/api/src/routes/operators/operatorRoutes.ts b/packages/api/src/routes/operators/operatorRoutes.ts index bf5e71ac..c52846ff 100644 --- a/packages/api/src/routes/operators/operatorRoutes.ts +++ b/packages/api/src/routes/operators/operatorRoutes.ts @@ -1,5 +1,6 @@ import express from 'express' -import { getAllOperators, getOperator } from './operatorController' +import { getAllOperators, getOperator, invalidateMetadata } from './operatorController' +import { authenticateJWT } from '../../utils/jwtUtils' import routeCache from "route-cache"; @@ -97,4 +98,12 @@ router.get('/', routeCache.cacheSeconds(120), getAllOperators) */ router.get('/:address', routeCache.cacheSeconds(120), getOperator) +// Protected routes +router.get( + '/:address/invalidate-metadata', + authenticateJWT, + routeCache.cacheSeconds(120), + invalidateMetadata +) + export default router diff --git a/packages/api/src/utils/jwtUtils.ts b/packages/api/src/utils/jwtUtils.ts index d013c9a0..24bcf471 100644 --- a/packages/api/src/utils/jwtUtils.ts +++ b/packages/api/src/utils/jwtUtils.ts @@ -23,4 +23,4 @@ export function authenticateJWT( } catch (error) { res.status(400).json({ message: 'Invalid token.' }) } -} \ No newline at end of file +} diff --git a/packages/seeder/src/monitors/avsMetadata.ts b/packages/seeder/src/monitors/avsMetadata.ts index 7258308f..579e9ee2 100644 --- a/packages/seeder/src/monitors/avsMetadata.ts +++ b/packages/seeder/src/monitors/avsMetadata.ts @@ -73,4 +73,4 @@ export async function monitorAvsMetadata() { await bulkUpdateDbTransactions(dbTransactions) console.log('Updated AVS metadatas: ', metadataList.size) -} \ No newline at end of file +} diff --git a/packages/seeder/src/monitors/operatorMetadata.ts b/packages/seeder/src/monitors/operatorMetadata.ts index e49242bb..d654e62b 100644 --- a/packages/seeder/src/monitors/operatorMetadata.ts +++ b/packages/seeder/src/monitors/operatorMetadata.ts @@ -1,76 +1,76 @@ import { getPrismaClient } from '../utils/prismaClient' - import type { EntityMetadata } from '../utils/metadata' - import { fetchWithTimeout, bulkUpdateDbTransactions } from '../utils/seeder' - import { isValidMetadataUrl, validateMetadata } from '../utils/metadata' +import type { EntityMetadata } from '../utils/metadata' +import { fetchWithTimeout, bulkUpdateDbTransactions } from '../utils/seeder' +import { isValidMetadataUrl, validateMetadata } from '../utils/metadata' - export async function monitorOperatorMetadata() { - console.log('Monitoring Operator Metadata...') +export async function monitorOperatorMetadata() { + console.log('Monitoring Operator Metadata...') - const prismaClient = getPrismaClient() - const metadataList: Map = new Map() + const prismaClient = getPrismaClient() + const metadataList: Map = new Map() - let skip = 0 - const take = 100 + let skip = 0 + const take = 100 - while (true) { - const operatorEntries = await prismaClient.operator.findMany({ - where: { - isMetadataSynced: false - }, - take: take, - skip: skip, - orderBy: { - createdAtBlock: 'desc' - } - }) + while (true) { + const operatorEntries = await prismaClient.operator.findMany({ + where: { + isMetadataSynced: false + }, + take: take, + skip: skip, + orderBy: { + createdAtBlock: 'desc' + } + }) - if (operatorEntries.length === 0) { - break - } + if (operatorEntries.length === 0) { + break + } - for (const record of operatorEntries) { - try { - if (record.metadataUrl && isValidMetadataUrl(record.metadataUrl)) { - const response = await fetchWithTimeout(record.metadataUrl) - const data = response ? await response.text() : '' - const operatorMetadata = validateMetadata(data) + for (const record of operatorEntries) { + try { + if (record.metadataUrl && isValidMetadataUrl(record.metadataUrl)) { + const response = await fetchWithTimeout(record.metadataUrl) + const data = response ? await response.text() : '' + const operatorMetadata = validateMetadata(data) - if (operatorMetadata) { - metadataList.set(record.address, operatorMetadata) - } else { - throw new Error('Invalid operator metadata uri') - } - } else { - throw new Error('Invalid operator metadata uri') - } - } catch (error) {} - } - skip += take - } + if (operatorMetadata) { + metadataList.set(record.address, operatorMetadata) + } else { + throw new Error('Invalid operator metadata uri') + } + } else { + throw new Error('Invalid operator metadata uri') + } + } catch (error) {} + } + skip += take + } - // Prepare db transaction object - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] + // Prepare db transaction object + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] - for (const [address, metadata] of metadataList) { - dbTransactions.push( - prismaClient.operator.update({ - where: { address }, - data: { - metadataName: metadata.name, - metadataDescription: metadata.description, - metadataLogo: metadata.logo, - metadataDiscord: metadata.discord, - metadataTelegram: metadata.telegram, - metadataWebsite: metadata.website, - metadataX: metadata.x, - isMetadataSynced: true - } - }) - ) - } + for (const [address, metadata] of metadataList) { + dbTransactions.push( + prismaClient.operator.update({ + where: { address }, + data: { + metadataName: metadata.name, + metadataDescription: metadata.description, + metadataLogo: metadata.logo, + metadataDiscord: metadata.discord, + metadataTelegram: metadata.telegram, + metadataWebsite: metadata.website, + metadataX: metadata.x, + isMetadataSynced: true + } + }) + ) + } - await bulkUpdateDbTransactions(dbTransactions) + await bulkUpdateDbTransactions(dbTransactions) - console.log('Updated Operator metadatas: ', metadataList.size) - } \ No newline at end of file + console.log('Updated Operator metadatas: ', metadataList.size) +} diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 5b282534..319593f7 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -80,7 +80,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { createdAt: timestamp, // Will be omitted in upsert if avs exists in db updatedAt: timestamp }) - } + } } // Prepare db transaction object @@ -94,7 +94,15 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { for (const [ address, - { metadataUrl, metadata, isMetadataSynced, createdAtBlock, updatedAtBlock, createdAt, updatedAt } + { + metadataUrl, + metadata, + isMetadataSynced, + createdAtBlock, + updatedAtBlock, + createdAt, + updatedAt + } ] of avsList) { newAvs.push({ address, @@ -123,7 +131,15 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { } else { for (const [ address, - { metadataUrl, metadata, isMetadataSynced, createdAtBlock, updatedAtBlock, createdAt, updatedAt } + { + metadataUrl, + metadata, + isMetadataSynced, + createdAtBlock, + updatedAtBlock, + createdAt, + updatedAt + } ] of avsList) { dbTransactions.push( prismaClient.avs.upsert({ diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index 3e0075b7..6ae67ae0 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -82,7 +82,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { createdAt: timestamp, updatedAt: timestamp }) - } + } } // Prepare db transaction object @@ -96,7 +96,15 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { for (const [ address, - { metadataUrl, metadata, isMetadataSynced, createdAtBlock, updatedAtBlock, createdAt, updatedAt } + { + metadataUrl, + metadata, + isMetadataSynced, + createdAtBlock, + updatedAtBlock, + createdAt, + updatedAt + } ] of operatorList) { newOperator.push({ address, @@ -125,7 +133,15 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { } else { for (const [ address, - { metadataUrl, metadata, isMetadataSynced, createdAtBlock, updatedAtBlock, createdAt, updatedAt } + { + metadataUrl, + metadata, + isMetadataSynced, + createdAtBlock, + updatedAtBlock, + createdAt, + updatedAt + } ] of operatorList) { dbTransactions.push( prismaClient.operator.upsert({ From 852a490528d744d018c8f1041a2d7381ceae998b Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 7 Jun 2024 14:42:46 +0530 Subject: [PATCH 45/62] altered how isMetadataSynced is handled in api response --- packages/api/src/routes/avs/avsController.ts | 12 ++++++++---- .../api/src/routes/operators/operatorController.ts | 12 ++++++++---- packages/seeder/src/index.ts | 10 +++++++--- packages/seeder/src/monitors/operatorMetadata.ts | 2 -- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/api/src/routes/avs/avsController.ts b/packages/api/src/routes/avs/avsController.ts index e0b4b2a1..845b8a6f 100644 --- a/packages/api/src/routes/avs/avsController.ts +++ b/packages/api/src/routes/avs/avsController.ts @@ -59,7 +59,7 @@ export async function getAllAVS(req: Request, res: Response) { : [] const data = await Promise.all( - avsRecords.map(async ({ isMetadataSynced, ...avs }) => { + avsRecords.map(async (avs) => { const restakeableStrategies = await getRestakeableStrategies( avs.address ) @@ -93,7 +93,9 @@ export async function getAllAVS(req: Request, res: Response) { strategyTokenPrices ) : undefined, - operators: undefined + operators: undefined, + metadataUrl: undefined, + isMetadataSynced: undefined } }) ) @@ -177,7 +179,7 @@ export async function getAVS(req: Request, res: Response) { const { address } = req.params const { withTvl } = req.query - const { isMetadataSynced, ...avs } = await prisma.avs.findUniqueOrThrow({ + const avs = await prisma.avs.findUniqueOrThrow({ where: { address: address.toLowerCase(), ...getAvsFilterQuery() }, include: { curatedMetadata: true, @@ -227,7 +229,9 @@ export async function getAVS(req: Request, res: Response) { strategyTokenPrices ) : undefined, - operators: undefined + operators: undefined, + metadataUrl: undefined, + isMetadataSynced: undefined }) } catch (error) { handleAndReturnErrorResponse(req, res, error) diff --git a/packages/api/src/routes/operators/operatorController.ts b/packages/api/src/routes/operators/operatorController.ts index 3eb1e218..8f4145ca 100644 --- a/packages/api/src/routes/operators/operatorController.ts +++ b/packages/api/src/routes/operators/operatorController.ts @@ -45,7 +45,7 @@ export async function getAllOperators(req: Request, res: Response) { ? await getStrategiesWithShareUnderlying() : [] - const operators = operatorRecords.map(({ isMetadataSynced, ...operator }) => ({ + const operators = operatorRecords.map((operator) => ({ ...operator, createdAtBlock: operator.createdAtBlock.toString(), updatedAtBlock: operator.updatedAtBlock.toString(), @@ -57,7 +57,9 @@ export async function getAllOperators(req: Request, res: Response) { strategyTokenPrices ) : undefined, - stakers: undefined + stakers: undefined, + metadataUrl: undefined, + isMetadataSynced: undefined })) res.send({ @@ -90,7 +92,7 @@ export async function getOperator(req: Request, res: Response) { try { const { address } = req.params - const { isMetadataSynced, ...operator } = await prisma.operator.findUniqueOrThrow({ + const operator = await prisma.operator.findUniqueOrThrow({ where: { address: address.toLowerCase() }, include: { shares: { @@ -118,7 +120,9 @@ export async function getOperator(req: Request, res: Response) { strategyTokenPrices ) : undefined, - stakers: undefined + stakers: undefined, + metadataUrl: undefined, + isMetadataSynced: undefined }) } catch (error) { handleAndReturnErrorResponse(req, res, error) diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 1e5bcd5d..f8fd2ba6 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -79,13 +79,17 @@ async function seedEigenPodValidators() { } } -async function monitorMetadatas() { +async function monitorMetadata() { + await delay(120) + while (true) { try { + console.log('\Monitoring Metadata...') + await monitorAvsMetadata() await monitorOperatorMetadata() } catch (error) { - console.log('Failed to monitor metadatas at: ', Date.now()) + console.log('Failed to monitor metadata at: ', Date.now()) } await delay(420) // Wait for 7 minutes (420 seconds) @@ -94,4 +98,4 @@ async function monitorMetadatas() { seedEigenDataLoop() seedEigenPodValidators() -monitorMetadatas() +monitorMetadata() diff --git a/packages/seeder/src/monitors/operatorMetadata.ts b/packages/seeder/src/monitors/operatorMetadata.ts index d654e62b..b41d23dd 100644 --- a/packages/seeder/src/monitors/operatorMetadata.ts +++ b/packages/seeder/src/monitors/operatorMetadata.ts @@ -4,8 +4,6 @@ import { fetchWithTimeout, bulkUpdateDbTransactions } from '../utils/seeder' import { isValidMetadataUrl, validateMetadata } from '../utils/metadata' export async function monitorOperatorMetadata() { - console.log('Monitoring Operator Metadata...') - const prismaClient = getPrismaClient() const metadataList: Map = new Map() From 6700671c024c23468314dd71b25179e1cbc2b288 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 7 Jun 2024 14:44:38 +0530 Subject: [PATCH 46/62] fixed typo --- packages/seeder/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index f8fd2ba6..fba51dbd 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -84,7 +84,7 @@ async function monitorMetadata() { while (true) { try { - console.log('\Monitoring Metadata...') + console.log('\nMonitoring Metadata...') await monitorAvsMetadata() await monitorOperatorMetadata() From 2bf950c3a916eb9d699f2289bc7606c957c5f061 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 7 Jun 2024 16:49:30 +0530 Subject: [PATCH 47/62] optimizations to monitors --- packages/seeder/src/monitors/avsMetadata.ts | 54 +++++++++---------- .../seeder/src/monitors/operatorMetadata.ts | 52 +++++++++--------- 2 files changed, 48 insertions(+), 58 deletions(-) diff --git a/packages/seeder/src/monitors/avsMetadata.ts b/packages/seeder/src/monitors/avsMetadata.ts index 579e9ee2..8d7e07ab 100644 --- a/packages/seeder/src/monitors/avsMetadata.ts +++ b/packages/seeder/src/monitors/avsMetadata.ts @@ -1,18 +1,17 @@ import { getPrismaClient } from '../utils/prismaClient' -import type { EntityMetadata } from '../utils/metadata' import { fetchWithTimeout, bulkUpdateDbTransactions } from '../utils/seeder' import { isValidMetadataUrl, validateMetadata } from '../utils/metadata' export async function monitorAvsMetadata() { - console.log('Monitoring AVS Metadata...') - const prismaClient = getPrismaClient() - const metadataList: Map = new Map() let skip = 0 const take = 100 while (true) { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + const avsEntries = await prismaClient.avs.findMany({ where: { isMetadataSynced: false @@ -20,7 +19,7 @@ export async function monitorAvsMetadata() { take: take, skip: skip, orderBy: { - createdAtBlock: 'desc' + createdAtBlock: 'asc' } }) @@ -36,7 +35,21 @@ export async function monitorAvsMetadata() { const avsMetadata = validateMetadata(data) if (avsMetadata) { - metadataList.set(record.address, avsMetadata) + dbTransactions.push( + prismaClient.avs.update({ + where: { address: record.address }, + data: { + metadataName: avsMetadata.name, + metadataDescription: avsMetadata.description, + metadataLogo: avsMetadata.logo, + metadataDiscord: avsMetadata.discord, + metadataTelegram: avsMetadata.telegram, + metadataWebsite: avsMetadata.website, + metadataX: avsMetadata.x, + isMetadataSynced: true + } + }) + ) } else { throw new Error('Invalid avs metadata uri') } @@ -45,32 +58,13 @@ export async function monitorAvsMetadata() { } } catch (error) {} } - skip += take - } - // Prepare db transaction object - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] - - for (const [address, metadata] of metadataList) { - dbTransactions.push( - prismaClient.avs.update({ - where: { address }, - data: { - metadataName: metadata.name, - metadataDescription: metadata.description, - metadataLogo: metadata.logo, - metadataDiscord: metadata.discord, - metadataTelegram: metadata.telegram, - metadataWebsite: metadata.website, - metadataX: metadata.x, - isMetadataSynced: true - } - }) + await bulkUpdateDbTransactions( + dbTransactions, + `[Monitor] Updated AVS metadatas: ${avsEntries.length}` ) + skip += take } - await bulkUpdateDbTransactions(dbTransactions) - - console.log('Updated AVS metadatas: ', metadataList.size) + console.log('[Monitor] All AVS metadatas up-to-date') } diff --git a/packages/seeder/src/monitors/operatorMetadata.ts b/packages/seeder/src/monitors/operatorMetadata.ts index b41d23dd..71ef35ca 100644 --- a/packages/seeder/src/monitors/operatorMetadata.ts +++ b/packages/seeder/src/monitors/operatorMetadata.ts @@ -1,16 +1,17 @@ import { getPrismaClient } from '../utils/prismaClient' -import type { EntityMetadata } from '../utils/metadata' import { fetchWithTimeout, bulkUpdateDbTransactions } from '../utils/seeder' import { isValidMetadataUrl, validateMetadata } from '../utils/metadata' export async function monitorOperatorMetadata() { const prismaClient = getPrismaClient() - const metadataList: Map = new Map() let skip = 0 const take = 100 while (true) { + // biome-ignore lint/suspicious/noExplicitAny: + const dbTransactions: any[] = [] + const operatorEntries = await prismaClient.operator.findMany({ where: { isMetadataSynced: false @@ -18,7 +19,7 @@ export async function monitorOperatorMetadata() { take: take, skip: skip, orderBy: { - createdAtBlock: 'desc' + createdAtBlock: 'asc' } }) @@ -34,7 +35,21 @@ export async function monitorOperatorMetadata() { const operatorMetadata = validateMetadata(data) if (operatorMetadata) { - metadataList.set(record.address, operatorMetadata) + dbTransactions.push( + prismaClient.operator.update({ + where: { address: record.address }, + data: { + metadataName: operatorMetadata.name, + metadataDescription: operatorMetadata.description, + metadataLogo: operatorMetadata.logo, + metadataDiscord: operatorMetadata.discord, + metadataTelegram: operatorMetadata.telegram, + metadataWebsite: operatorMetadata.website, + metadataX: operatorMetadata.x, + isMetadataSynced: true + } + }) + ) } else { throw new Error('Invalid operator metadata uri') } @@ -43,32 +58,13 @@ export async function monitorOperatorMetadata() { } } catch (error) {} } - skip += take - } - - // Prepare db transaction object - // biome-ignore lint/suspicious/noExplicitAny: - const dbTransactions: any[] = [] - for (const [address, metadata] of metadataList) { - dbTransactions.push( - prismaClient.operator.update({ - where: { address }, - data: { - metadataName: metadata.name, - metadataDescription: metadata.description, - metadataLogo: metadata.logo, - metadataDiscord: metadata.discord, - metadataTelegram: metadata.telegram, - metadataWebsite: metadata.website, - metadataX: metadata.x, - isMetadataSynced: true - } - }) + await bulkUpdateDbTransactions( + dbTransactions, + `[Monitor] Updated Operator metadatas: ${operatorEntries.length}` ) + skip += take } - await bulkUpdateDbTransactions(dbTransactions) - - console.log('Updated Operator metadatas: ', metadataList.size) + console.log('[Monitor] All Operator metadatas up-to-date') } From 6e15b201e10650dd95e21a6871e16cff3a179bfe Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 7 Jun 2024 17:47:03 +0530 Subject: [PATCH 48/62] fixed count in monitor logging --- packages/seeder/src/index.ts | 14 +++++++------- packages/seeder/src/monitors/avsMetadata.ts | 10 ++++++---- packages/seeder/src/monitors/operatorMetadata.ts | 12 +++++++----- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index fba51dbd..6121a6cd 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -22,7 +22,7 @@ import { seedLogsWithdrawalCompleted } from './events/seedLogsWithdrawalComplete import { monitorAvsMetadata } from './monitors/avsMetadata' import { monitorOperatorMetadata } from './monitors/operatorMetadata' -console.log('Initializing seeder ...') +console.log('Initializing Seeder ...') function delay(seconds: number) { return new Promise((resolve) => setTimeout(resolve, seconds * 1000)) @@ -33,7 +33,7 @@ async function seedEigenDataLoop() { try { const viemClient = getViemClient() const targetBlock = await viemClient.getBlockNumber() - console.log('\nSeeding Data ...', targetBlock) + console.log('\nSeeding data ...', targetBlock) await seedBlockData(targetBlock) await seedLogsAVSMetadata(targetBlock) @@ -66,16 +66,16 @@ async function seedEigenPodValidators() { while (true) { try { - console.log('\nSeeding Eigen Pods Data ...') + console.log('\nSeeding Eigen Pods data ...') await seedPods() await seedValidators() } catch (error) { - console.log('Failed to seed validators at block:', Date.now()) + console.log('Failed to seed Validators at block:', Date.now()) console.log(error) } - await delay(600) // Wait for 10 minutes (600 seconds) + await delay(600) } } @@ -84,7 +84,7 @@ async function monitorMetadata() { while (true) { try { - console.log('\nMonitoring Metadata...') + console.log('\nMonitoring metadata...') await monitorAvsMetadata() await monitorOperatorMetadata() @@ -92,7 +92,7 @@ async function monitorMetadata() { console.log('Failed to monitor metadata at: ', Date.now()) } - await delay(420) // Wait for 7 minutes (420 seconds) + await delay(420) } } diff --git a/packages/seeder/src/monitors/avsMetadata.ts b/packages/seeder/src/monitors/avsMetadata.ts index 8d7e07ab..746442e8 100644 --- a/packages/seeder/src/monitors/avsMetadata.ts +++ b/packages/seeder/src/monitors/avsMetadata.ts @@ -59,10 +59,12 @@ export async function monitorAvsMetadata() { } catch (error) {} } - await bulkUpdateDbTransactions( - dbTransactions, - `[Monitor] Updated AVS metadatas: ${avsEntries.length}` - ) + if (dbTransactions.length > 0) { + await bulkUpdateDbTransactions( + dbTransactions, + `[Monitor] Updated AVS metadatas: ${dbTransactions.length}` + ) + } skip += take } diff --git a/packages/seeder/src/monitors/operatorMetadata.ts b/packages/seeder/src/monitors/operatorMetadata.ts index 71ef35ca..15e668f3 100644 --- a/packages/seeder/src/monitors/operatorMetadata.ts +++ b/packages/seeder/src/monitors/operatorMetadata.ts @@ -58,11 +58,13 @@ export async function monitorOperatorMetadata() { } } catch (error) {} } - - await bulkUpdateDbTransactions( - dbTransactions, - `[Monitor] Updated Operator metadatas: ${operatorEntries.length}` - ) + + if (dbTransactions.length > 0) { + await bulkUpdateDbTransactions( + dbTransactions, + `[Monitor] Updated Operator metadatas: ${dbTransactions.length}` + ) + } skip += take } From 93abb50e799538a9281b4ebb54099fda51347371 Mon Sep 17 00:00:00 2001 From: Gowtham S Date: Fri, 7 Jun 2024 18:41:24 +0530 Subject: [PATCH 49/62] rectified console log --- packages/seeder/src/seedPods.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index f1cf0ad9..684097bf 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -102,7 +102,7 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { await bulkUpdateDbTransactions( dbTransactions, - `[Data] AVS MetadataURI from: ${firstBlock} to: ${lastBlock} size: ${podList.length}` + `[Data] Pods from: ${firstBlock} to: ${lastBlock} size: ${podList.length}` ) // Storing last sycned block From d5cae2de8f830c737d549c694753c34e9fed07ec Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Mon, 10 Jun 2024 21:31:17 +0530 Subject: [PATCH 50/62] Include migrations for metadata url and deposit logs --- .../migration.sql | 7 ++++ .../migration.sql | 34 +++++++++++++++++++ packages/prisma/schema.prisma | 14 ++++---- 3 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 packages/prisma/migrations/20240610150322_include_metadata_url_avs_operator/migration.sql create mode 100644 packages/prisma/migrations/20240610150614_include_deposit_logs_data/migration.sql diff --git a/packages/prisma/migrations/20240610150322_include_metadata_url_avs_operator/migration.sql b/packages/prisma/migrations/20240610150322_include_metadata_url_avs_operator/migration.sql new file mode 100644 index 00000000..2d34d700 --- /dev/null +++ b/packages/prisma/migrations/20240610150322_include_metadata_url_avs_operator/migration.sql @@ -0,0 +1,7 @@ +-- AlterTable +ALTER TABLE "Avs" ADD COLUMN "isMetadataSynced" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "metadataUrl" TEXT; + +-- AlterTable +ALTER TABLE "Operator" ADD COLUMN "isMetadataSynced" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "metadataUrl" TEXT; diff --git a/packages/prisma/migrations/20240610150614_include_deposit_logs_data/migration.sql b/packages/prisma/migrations/20240610150614_include_deposit_logs_data/migration.sql new file mode 100644 index 00000000..bdd02dba --- /dev/null +++ b/packages/prisma/migrations/20240610150614_include_deposit_logs_data/migration.sql @@ -0,0 +1,34 @@ +-- CreateTable +CREATE TABLE "Deposit" ( + "transactionHash" TEXT NOT NULL, + "stakerAddress" TEXT NOT NULL, + "tokenAddress" TEXT NOT NULL, + "strategyAddress" TEXT NOT NULL, + "shares" TEXT NOT NULL, + "createdAtBlock" BIGINT NOT NULL DEFAULT 0, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Deposit_pkey" PRIMARY KEY ("transactionHash") +); + +-- CreateTable +CREATE TABLE "EventLogs_Deposit" ( + "address" TEXT NOT NULL, + "transactionHash" TEXT NOT NULL, + "transactionIndex" INTEGER NOT NULL, + "blockNumber" BIGINT NOT NULL, + "blockHash" TEXT NOT NULL, + "blockTime" TIMESTAMP(3) NOT NULL, + "staker" TEXT NOT NULL, + "token" TEXT NOT NULL, + "strategy" TEXT NOT NULL, + "shares" TEXT NOT NULL, + + CONSTRAINT "EventLogs_Deposit_pkey" PRIMARY KEY ("transactionHash","transactionIndex") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Deposit_transactionHash_key" ON "Deposit"("transactionHash"); + +-- CreateIndex +CREATE INDEX "EventLogs_Deposit_staker_idx" ON "EventLogs_Deposit"("staker"); diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index baf46f7d..5b73d023 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -11,7 +11,7 @@ datasource db { model Avs { address String @id @unique - metadataUrl String + metadataUrl String? metadataName String metadataDescription String metadataDiscord String? @@ -67,7 +67,7 @@ model Strategies { model Operator { address String @id @unique - metadataUrl String + metadataUrl String? metadataName String metadataDescription String metadataDiscord String? @@ -102,7 +102,7 @@ model Staker { operator Operator? @relation(fields: [operatorAddress], references: [address]) operatorAddress String? - shares StakerStrategyShares[] + shares StakerStrategyShares[] createdAtBlock BigInt @default(0) updatedAtBlock BigInt @default(0) @@ -120,14 +120,14 @@ model StakerStrategyShares { } model Deposit { - transactionHash String @id @unique - stakerAddress String + transactionHash String @id @unique + stakerAddress String tokenAddress String strategyAddress String shares String - createdAtBlock BigInt @default(0) - createdAt DateTime @default(now()) + createdAtBlock BigInt @default(0) + createdAt DateTime @default(now()) } model Pod { From 38440d4f91f0b1b15e70fb93732236b17e553655 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Mon, 10 Jun 2024 21:31:53 +0530 Subject: [PATCH 51/62] Fix query logic for operator / staker shares --- packages/seeder/src/seedOperatorShares.ts | 2 +- packages/seeder/src/seedStakers.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/seeder/src/seedOperatorShares.ts b/packages/seeder/src/seedOperatorShares.ts index d999182c..9137e1fc 100644 --- a/packages/seeder/src/seedOperatorShares.ts +++ b/packages/seeder/src/seedOperatorShares.ts @@ -55,7 +55,7 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: firstBlock, + gt: firstBlock, lte: lastBlock } } diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index 203175c0..1d59f133 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -63,7 +63,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: firstBlock, + gt: firstBlock, lte: lastBlock } } @@ -82,7 +82,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: firstBlock, + gt: firstBlock, lte: lastBlock } } @@ -101,7 +101,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { .findMany({ where: { blockNumber: { - gte: firstBlock, + gt: firstBlock, lte: lastBlock } } From 39cc94cb09c7098a315fa0d9c09d36ec5a846a93 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Mon, 10 Jun 2024 21:32:32 +0530 Subject: [PATCH 52/62] Fix first block cascading deletion of avs operator --- packages/seeder/src/seedAvs.ts | 1 + packages/seeder/src/seedOperators.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 319593f7..19baa5c8 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -88,6 +88,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { const dbTransactions: any[] = [] if (firstBlock === baseBlock) { + dbTransactions.push(prismaClient.avsOperator.deleteMany()) dbTransactions.push(prismaClient.avs.deleteMany()) const newAvs: prisma.Avs[] = [] diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index 6ae67ae0..9d1461f2 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -90,6 +90,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { const dbTransactions: any[] = [] if (firstBlock === baseBlock) { + dbTransactions.push(prismaClient.avsOperator.deleteMany()) dbTransactions.push(prismaClient.operator.deleteMany()) const newOperator: prisma.Operator[] = [] From 63f5b360d241bc5fe08aa7dc303414c38adb1e59 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Mon, 10 Jun 2024 21:32:55 +0530 Subject: [PATCH 53/62] Fix data value provided for logs composite key --- .../seeder/src/events/seedLogsAVSMetadata.ts | 15 +++-- packages/seeder/src/events/seedLogsDeposit.ts | 15 +++-- .../seedLogsOperatorAVSRegistrationStatus.ts | 15 +++-- .../src/events/seedLogsOperatorMetadata.ts | 17 +++--- .../src/events/seedLogsOperatorShares.ts | 57 ++++++++++--------- .../seeder/src/events/seedLogsPodDeployed.ts | 15 +++-- .../src/events/seedLogsStakerDelegation.ts | 51 +++++++++-------- .../src/events/seedLogsWithdrawalCompleted.ts | 5 +- .../src/events/seedLogsWithdrawalQueued.ts | 5 +- 9 files changed, 98 insertions(+), 97 deletions(-) diff --git a/packages/seeder/src/events/seedLogsAVSMetadata.ts b/packages/seeder/src/events/seedLogsAVSMetadata.ts index 15f916d9..c77285d3 100644 --- a/packages/seeder/src/events/seedLogsAVSMetadata.ts +++ b/packages/seeder/src/events/seedLogsAVSMetadata.ts @@ -29,10 +29,11 @@ export async function seedLogsAVSMetadata( ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - const blockData = await getBlockDataFromDb(firstBlock, lastBlock) // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + const blockData = await getBlockDataFromDb(fromBlock, toBlock) + try { // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -40,12 +41,10 @@ export async function seedLogsAVSMetadata( [] const logs = await viemClient.getLogs({ - address: [getEigenContracts().AVSDirectory], - events: [ - parseAbiItem( - 'event AVSMetadataURIUpdated(address indexed avs, string metadataURI)' - ) - ], + address: getEigenContracts().AVSDirectory, + event: parseAbiItem( + 'event AVSMetadataURIUpdated(address indexed avs, string metadataURI)' + ), fromBlock, toBlock }) @@ -57,7 +56,7 @@ export async function seedLogsAVSMetadata( logsAVSMetadataURIUpdated.push({ address: log.address, transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, + transactionIndex: log.logIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), diff --git a/packages/seeder/src/events/seedLogsDeposit.ts b/packages/seeder/src/events/seedLogsDeposit.ts index acc505cf..9aabd6a2 100644 --- a/packages/seeder/src/events/seedLogsDeposit.ts +++ b/packages/seeder/src/events/seedLogsDeposit.ts @@ -26,22 +26,21 @@ export async function seedLogsDeposit(toBlock?: bigint, fromBlock?: bigint) { ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - const blockData = await getBlockDataFromDb(firstBlock, lastBlock) // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + const blockData = await getBlockDataFromDb(fromBlock, toBlock) + try { // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] const logsDeposit: prisma.EventLogs_Deposit[] = [] const logs = await viemClient.getLogs({ - address: [getEigenContracts().StrategyManager], - events: [ - parseAbiItem( - 'event Deposit(address staker, address token, address strategy, uint256 shares)' - ) - ], + address: getEigenContracts().StrategyManager, + event: parseAbiItem( + 'event Deposit(address staker, address token, address strategy, uint256 shares)' + ), fromBlock, toBlock }) @@ -53,7 +52,7 @@ export async function seedLogsDeposit(toBlock?: bigint, fromBlock?: bigint) { logsDeposit.push({ address: log.address, transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, + transactionIndex: log.logIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), diff --git a/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts b/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts index 47ed0c1a..9fae1efa 100644 --- a/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts +++ b/packages/seeder/src/events/seedLogsOperatorAVSRegistrationStatus.ts @@ -29,10 +29,11 @@ export async function seedLogsOperatorAVSRegistrationStatus( ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - const blockData = await getBlockDataFromDb(firstBlock, lastBlock) // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + const blockData = await getBlockDataFromDb(fromBlock, toBlock) + try { // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -41,12 +42,10 @@ export async function seedLogsOperatorAVSRegistrationStatus( [] const logs = await viemClient.getLogs({ - address: [getEigenContracts().AVSDirectory], - events: [ - parseAbiItem( - 'event OperatorAVSRegistrationStatusUpdated(address indexed operator, address indexed avs, uint8 status)' - ) - ], + address: getEigenContracts().AVSDirectory, + event: parseAbiItem( + 'event OperatorAVSRegistrationStatusUpdated(address indexed operator, address indexed avs, uint8 status)' + ), fromBlock, toBlock }) @@ -58,7 +57,7 @@ export async function seedLogsOperatorAVSRegistrationStatus( logsOperatorAVSRegistrationStatusUpdated.push({ address: log.address, transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, + transactionIndex: log.logIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), diff --git a/packages/seeder/src/events/seedLogsOperatorMetadata.ts b/packages/seeder/src/events/seedLogsOperatorMetadata.ts index 5e8e2f76..57dab343 100644 --- a/packages/seeder/src/events/seedLogsOperatorMetadata.ts +++ b/packages/seeder/src/events/seedLogsOperatorMetadata.ts @@ -29,10 +29,11 @@ export async function seedLogsOperatorMetadata( ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - const blockData = await getBlockDataFromDb(firstBlock, lastBlock) // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + const blockData = await getBlockDataFromDb(fromBlock, toBlock) + try { // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -40,12 +41,10 @@ export async function seedLogsOperatorMetadata( [] const logs = await viemClient.getLogs({ - address: [getEigenContracts().DelegationManager], - events: [ - parseAbiItem( - 'event OperatorMetadataURIUpdated(address indexed operator, string metadataURI)' - ) - ], + address: getEigenContracts().DelegationManager, + event: parseAbiItem( + 'event OperatorMetadataURIUpdated(address indexed operator, string metadataURI)' + ), fromBlock, toBlock }) @@ -57,7 +56,7 @@ export async function seedLogsOperatorMetadata( logsOperatorMetadataURIUpdated.push({ address: log.address, transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, + transactionIndex: log.logIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), @@ -84,7 +83,7 @@ export async function seedLogsOperatorMetadata( // Update database const seedLength = logsOperatorMetadataURIUpdated.length - + await bulkUpdateDbTransactions( dbTransactions, `[Logs] Operator Metadata from: ${fromBlock} to: ${toBlock} size: ${seedLength}` diff --git a/packages/seeder/src/events/seedLogsOperatorShares.ts b/packages/seeder/src/events/seedLogsOperatorShares.ts index 5c69b035..ab281131 100644 --- a/packages/seeder/src/events/seedLogsOperatorShares.ts +++ b/packages/seeder/src/events/seedLogsOperatorShares.ts @@ -29,10 +29,11 @@ export async function seedLogsOperatorShares( ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - const blockData = await getBlockDataFromDb(firstBlock, lastBlock) // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + const blockData = await getBlockDataFromDb(fromBlock, toBlock) + try { // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -42,7 +43,7 @@ export async function seedLogsOperatorShares( [] const logs = await viemClient.getLogs({ - address: [getEigenContracts().DelegationManager], + address: getEigenContracts().DelegationManager, events: [ parseAbiItem( 'event OperatorSharesIncreased(address indexed operator, address staker, address strategy, uint256 shares)' @@ -59,31 +60,33 @@ export async function seedLogsOperatorShares( for (const l in logs) { const log = logs[l] - logsOperatorSharesIncreased.push({ - address: log.address, - transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, - blockNumber: BigInt(log.blockNumber), - blockHash: log.blockHash, - blockTime: blockData.get(log.blockNumber) || new Date(0), - operator: String(log.args.operator), - staker: String(log.args.staker), - strategy: String(log.args.strategy), - shares: String(log.args.shares) - }) - - logsOperatorSharesDecreased.push({ - address: log.address, - transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, - blockNumber: BigInt(log.blockNumber), - blockHash: log.blockHash, - blockTime: blockData.get(log.blockNumber) || new Date(0), - operator: String(log.args.operator), - staker: String(log.args.staker), - strategy: String(log.args.strategy), - shares: String(log.args.shares) - }) + if (log.eventName === 'OperatorSharesIncreased') { + logsOperatorSharesIncreased.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.logIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + operator: String(log.args.operator), + staker: String(log.args.staker), + strategy: String(log.args.strategy), + shares: String(log.args.shares) + }) + } else if (log.eventName === 'OperatorSharesDecreased') { + logsOperatorSharesDecreased.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.logIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + operator: String(log.args.operator), + staker: String(log.args.staker), + strategy: String(log.args.strategy), + shares: String(log.args.shares) + }) + } } dbTransactions.push( diff --git a/packages/seeder/src/events/seedLogsPodDeployed.ts b/packages/seeder/src/events/seedLogsPodDeployed.ts index 2c99ab50..dee25cfc 100644 --- a/packages/seeder/src/events/seedLogsPodDeployed.ts +++ b/packages/seeder/src/events/seedLogsPodDeployed.ts @@ -29,10 +29,11 @@ export async function seedLogsPodDeployed( ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - const blockData = await getBlockDataFromDb(firstBlock, lastBlock) // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + const blockData = await getBlockDataFromDb(fromBlock, toBlock) + try { // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -40,12 +41,10 @@ export async function seedLogsPodDeployed( const logsPodDeployed: prisma.EventLogs_PodDeployed[] = [] const logs = await viemClient.getLogs({ - address: [getEigenContracts().EigenPodManager], - events: [ - parseAbiItem( - 'event PodDeployed(address indexed eigenPod, address indexed podOwner)' - ) - ], + address: getEigenContracts().EigenPodManager, + event: parseAbiItem( + 'event PodDeployed(address indexed eigenPod, address indexed podOwner)' + ), fromBlock, toBlock }) @@ -57,7 +56,7 @@ export async function seedLogsPodDeployed( logsPodDeployed.push({ address: log.address, transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, + transactionIndex: log.logIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), diff --git a/packages/seeder/src/events/seedLogsStakerDelegation.ts b/packages/seeder/src/events/seedLogsStakerDelegation.ts index fc4ff6c9..48368e36 100644 --- a/packages/seeder/src/events/seedLogsStakerDelegation.ts +++ b/packages/seeder/src/events/seedLogsStakerDelegation.ts @@ -29,12 +29,11 @@ export async function seedLogsStakerDelegation( ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - const blockData = await getBlockDataFromDb(firstBlock, lastBlock) - - let totalSeeded = 0 // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + const blockData = await getBlockDataFromDb(fromBlock, toBlock) + try { // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -43,7 +42,7 @@ export async function seedLogsStakerDelegation( const logsStakerUndelegated: prisma.EventLogs_StakerUndelegated[] = [] const logs = await viemClient.getLogs({ - address: [getEigenContracts().DelegationManager], + address: getEigenContracts().DelegationManager, events: [ parseAbiItem( 'event StakerDelegated(address indexed staker, address indexed operator)' @@ -60,27 +59,29 @@ export async function seedLogsStakerDelegation( for (const l in logs) { const log = logs[l] - logsStakerDelegated.push({ - address: log.address, - transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, - blockNumber: BigInt(log.blockNumber), - blockHash: log.blockHash, - blockTime: blockData.get(log.blockNumber) || new Date(0), - staker: String(log.args.staker), - operator: String(log.args.operator) - }) - - logsStakerUndelegated.push({ - address: log.address, - transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, - blockNumber: BigInt(log.blockNumber), - blockHash: log.blockHash, - blockTime: blockData.get(log.blockNumber) || new Date(0), - staker: String(log.args.staker), - operator: String(log.args.operator) - }) + if (log.eventName === 'StakerDelegated') { + logsStakerDelegated.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.logIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + staker: String(log.args.staker), + operator: String(log.args.operator) + }) + } else if (log.eventName === 'StakerUndelegated') { + logsStakerUndelegated.push({ + address: log.address, + transactionHash: log.transactionHash, + transactionIndex: log.logIndex, + blockNumber: BigInt(log.blockNumber), + blockHash: log.blockHash, + blockTime: blockData.get(log.blockNumber) || new Date(0), + staker: String(log.args.staker), + operator: String(log.args.operator) + }) + } } dbTransactions.push( diff --git a/packages/seeder/src/events/seedLogsWithdrawalCompleted.ts b/packages/seeder/src/events/seedLogsWithdrawalCompleted.ts index 16736856..e0e74dca 100644 --- a/packages/seeder/src/events/seedLogsWithdrawalCompleted.ts +++ b/packages/seeder/src/events/seedLogsWithdrawalCompleted.ts @@ -29,10 +29,11 @@ export async function seedLogsWithdrawalCompleted( ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - const blockData = await getBlockDataFromDb(firstBlock, lastBlock) // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + const blockData = await getBlockDataFromDb(fromBlock, toBlock) + try { // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -55,7 +56,7 @@ export async function seedLogsWithdrawalCompleted( logsWithdrawalCompleted.push({ address: log.address, transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, + transactionIndex: log.logIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), diff --git a/packages/seeder/src/events/seedLogsWithdrawalQueued.ts b/packages/seeder/src/events/seedLogsWithdrawalQueued.ts index 1c9ea9cc..391c582b 100644 --- a/packages/seeder/src/events/seedLogsWithdrawalQueued.ts +++ b/packages/seeder/src/events/seedLogsWithdrawalQueued.ts @@ -29,10 +29,11 @@ export async function seedLogsWithdrawalQueued( ? fromBlock : await fetchLastSyncBlock(blockSyncKeyLogs) const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber() - const blockData = await getBlockDataFromDb(firstBlock, lastBlock) // Loop through evm logs await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + const blockData = await getBlockDataFromDb(fromBlock, toBlock) + try { // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] @@ -56,7 +57,7 @@ export async function seedLogsWithdrawalQueued( logsWithdrawalQueued.push({ address: log.address, transactionHash: log.transactionHash, - transactionIndex: log.transactionIndex, + transactionIndex: log.logIndex, blockNumber: BigInt(log.blockNumber), blockHash: log.blockHash, blockTime: blockData.get(log.blockNumber) || new Date(0), From 7e7fce180634db06cea35e517a81ee7bb163b279 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Mon, 10 Jun 2024 21:33:05 +0530 Subject: [PATCH 54/62] Temporarily disable other seeders --- packages/seeder/src/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index 1fff5120..d7b3bffd 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -56,6 +56,7 @@ async function seedEigenDataLoop() { await seedQueuedWithdrawals() await seedCompletedWithdrawals() await seedDeposits() + await seedPods() } catch (error) { console.log('Failed to seed data at:', Date.now()) console.log(error) @@ -101,5 +102,5 @@ async function monitorMetadata() { } seedEigenDataLoop() -seedEigenPodValidators() -monitorMetadata() +// seedEigenPodValidators() +// monitorMetadata() From 0eb45a7086277921d8958f8370c7990c8129138f Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Tue, 11 Jun 2024 01:08:58 +0530 Subject: [PATCH 55/62] Include log sorter and loop log fetch through blocks --- packages/seeder/src/seedAvs.ts | 90 ++--- packages/seeder/src/seedAvsOperators.ts | 46 ++- packages/seeder/src/seedDeposits.ts | 45 +-- packages/seeder/src/seedOperatorShares.ts | 194 ++++++----- packages/seeder/src/seedOperators.ts | 89 ++--- packages/seeder/src/seedPods.ts | 56 ++-- packages/seeder/src/seedStakers.ts | 308 +++++++++--------- .../seeder/src/seedWithdrawalsCompleted.ts | 38 ++- packages/seeder/src/seedWithdrawalsQueued.ts | 85 +++-- 9 files changed, 511 insertions(+), 440 deletions(-) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index 19baa5c8..fe007bde 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -5,6 +5,7 @@ import { baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, + loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -40,48 +41,55 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { return } - const logs = await prismaClient.eventLogs_AVSMetadataURIUpdated.findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock - } - } - }) - - for (const l in logs) { - const log = logs[l] - - const avsAddress = String(log.avs).toLowerCase() - const existingRecord = avsList.get(avsAddress) - - const blockNumber = BigInt(log.blockNumber) - const timestamp = log.blockTime - - if (existingRecord) { - // Avs has been registered before in this fetch - avsList.set(avsAddress, { - metadataUrl: log.metadataURI, - metadata: defaultMetadata, - isMetadataSynced: false, - createdAtBlock: existingRecord.createdAtBlock, - updatedAtBlock: blockNumber, - createdAt: existingRecord.createdAt, - updatedAt: timestamp - }) - } else { - // Avs being registered for the first time in this fetch - avsList.set(avsAddress, { - metadataUrl: log.metadataURI, - metadata: defaultMetadata, - isMetadataSynced: false, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, // Will be omitted in upsert if avs exists in db - updatedAt: timestamp + await loopThroughBlocks( + firstBlock, + lastBlock, + async (fromBlock, toBlock) => { + const logs = await prismaClient.eventLogs_AVSMetadataURIUpdated.findMany({ + where: { + blockNumber: { + gt: fromBlock, + lte: toBlock + } + } }) - } - } + + for (const l in logs) { + const log = logs[l] + + const avsAddress = String(log.avs).toLowerCase() + const existingRecord = avsList.get(avsAddress) + + const blockNumber = BigInt(log.blockNumber) + const timestamp = log.blockTime + + if (existingRecord) { + // Avs has been registered before in this fetch + avsList.set(avsAddress, { + metadataUrl: log.metadataURI, + metadata: defaultMetadata, + isMetadataSynced: false, + createdAtBlock: existingRecord.createdAtBlock, + updatedAtBlock: blockNumber, + createdAt: existingRecord.createdAt, + updatedAt: timestamp + }) + } else { + // Avs being registered for the first time in this fetch + avsList.set(avsAddress, { + metadataUrl: log.metadataURI, + metadata: defaultMetadata, + isMetadataSynced: false, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, // Will be omitted in upsert if avs exists in db + updatedAt: timestamp + }) + } + } + }, + 100_000n + ) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedAvsOperators.ts b/packages/seeder/src/seedAvsOperators.ts index 65f4bddd..9661ccda 100644 --- a/packages/seeder/src/seedAvsOperators.ts +++ b/packages/seeder/src/seedAvsOperators.ts @@ -3,6 +3,7 @@ import { baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, + loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -35,26 +36,37 @@ export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { avs.map((a) => avsOperatorsList.set(a.address, new Map())) - const logs = - await prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock - } - } - }) + await loopThroughBlocks( + firstBlock, + lastBlock, + async (fromBlock, toBlock) => { + const logs = + await prismaClient.eventLogs_OperatorAVSRegistrationStatusUpdated.findMany( + { + where: { + blockNumber: { + gt: fromBlock, + lte: toBlock + } + } + } + ) - for (const l in logs) { - const log = logs[l] + for (const l in logs) { + const log = logs[l] - const avsAddress = String(log.avs).toLowerCase() - const operatorAddress = String(log.operator).toLowerCase() + const avsAddress = String(log.avs).toLowerCase() + const operatorAddress = String(log.operator).toLowerCase() - if (avsOperatorsList.has(avsAddress)) { - avsOperatorsList.get(avsAddress)?.set(operatorAddress, log.status || 0) - } - } + if (avsOperatorsList.has(avsAddress)) { + avsOperatorsList + .get(avsAddress) + ?.set(operatorAddress, log.status || 0) + } + } + }, + 100_000n + ) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedDeposits.ts b/packages/seeder/src/seedDeposits.ts index 82fe6767..c877104a 100644 --- a/packages/seeder/src/seedDeposits.ts +++ b/packages/seeder/src/seedDeposits.ts @@ -3,6 +3,7 @@ import { getPrismaClient } from './utils/prismaClient' import { bulkUpdateDbTransactions, fetchLastSyncBlock, + loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -26,31 +27,33 @@ export async function seedDeposits(toBlock?: bigint, fromBlock?: bigint) { return } - const logs = await prismaClient.eventLogs_Deposit.findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock + await loopThroughBlocks(firstBlock, lastBlock, async (fromBlock, toBlock) => { + const logs = await prismaClient.eventLogs_Deposit.findMany({ + where: { + blockNumber: { + gt: fromBlock, + lte: toBlock + } } - } - }) + }) - for (const l in logs) { - const log = logs[l] + for (const l in logs) { + const log = logs[l] - const blockNumber = BigInt(log.blockNumber) - const timestamp = log.blockTime + const blockNumber = BigInt(log.blockNumber) + const timestamp = log.blockTime - depositList.push({ - transactionHash: log.transactionHash.toLowerCase(), - stakerAddress: log.staker.toLowerCase(), - tokenAddress: log.token.toLowerCase(), - strategyAddress: log.strategy.toLowerCase(), - shares: log.shares, - createdAtBlock: blockNumber, - createdAt: timestamp - }) - } + depositList.push({ + transactionHash: log.transactionHash.toLowerCase(), + stakerAddress: log.staker.toLowerCase(), + tokenAddress: log.token.toLowerCase(), + strategyAddress: log.strategy.toLowerCase(), + shares: log.shares, + createdAtBlock: blockNumber, + createdAt: timestamp + }) + } + }) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedOperatorShares.ts b/packages/seeder/src/seedOperatorShares.ts index 9137e1fc..5009f982 100644 --- a/packages/seeder/src/seedOperatorShares.ts +++ b/packages/seeder/src/seedOperatorShares.ts @@ -4,6 +4,7 @@ import { bulkUpdateDbTransactions, fetchLastSyncBlock, type IMap, + loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -36,102 +37,121 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { await prismaClient.operatorStrategyShares.deleteMany() } - const logsOperatorSharesIncreased = - await prismaClient.eventLogs_OperatorSharesIncreased - .findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock - } + await loopThroughBlocks( + firstBlock, + lastBlock, + async (fromBlock, toBlock) => { + // biome-ignore lint/suspicious/noExplicitAny: + let allLogs: any[] = [] + + await prismaClient.eventLogs_OperatorSharesIncreased + .findMany({ where: { blockNumber: { gt: fromBlock, lte: toBlock } } }) + .then((logs) => { + allLogs = [ + ...allLogs, + ...logs.map((log) => ({ + ...log, + eventName: 'OperatorSharesIncreased' + })) + ] + }) + + await prismaClient.eventLogs_OperatorSharesDecreased + .findMany({ where: { blockNumber: { gt: fromBlock, lte: toBlock } } }) + .then((logs) => { + allLogs = [ + ...allLogs, + ...logs.map((log) => ({ + ...log, + eventName: 'OperatorSharesDecreased' + })) + ] + }) + + allLogs = allLogs.sort((a, b) => { + if (a.blockNumber === b.blockNumber) { + return a.transactionIndex - b.transactionIndex } + + return Number(a.blockNumber - b.blockNumber) }) - .then((logs) => - logs.map((log) => ({ ...log, eventName: 'OperatorSharesIncreased' })) - ) - const logsOperatorSharesDecreased = - await prismaClient.eventLogs_OperatorSharesDecreased - .findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock + // Operators list + const operatorAddresses = allLogs.map((l) => + String(l.operator).toLowerCase() + ) + const operatorInit = + firstBlock !== baseBlock + ? await prismaClient.operator.findMany({ + where: { address: { in: operatorAddresses } }, + include: { + shares: true + } + }) + : [] + + for (const l in allLogs) { + const log = allLogs[l] + + const operatorAddress = String(log.operator).toLowerCase() + const strategyAddress = String(log.strategy).toLowerCase() + const shares = log.shares + if (!shares) continue + + // Load existing staker shares data + if (!operatorShares.has(operatorAddress)) { + const foundOperatorInit = operatorInit.find( + (o) => o.address.toLowerCase() === operatorAddress.toLowerCase() + ) + if (foundOperatorInit) { + operatorShares.set( + operatorAddress, + foundOperatorInit.shares.map((o) => ({ + ...o, + shares: BigInt(o.shares) + })) + ) + } else { + operatorShares.set(operatorAddress, []) } } - }) - .then((logs) => - logs.map((log) => ({ ...log, eventName: 'OperatorSharesDecreased' })) - ) - - const logs = [...logsOperatorSharesIncreased, ...logsOperatorSharesDecreased] - - // Operators list - const operatorAddresses = logs.map((l) => String(l.operator).toLowerCase()) - - const operatorInit = await prismaClient.operator.findMany({ - where: { address: { in: operatorAddresses } }, - include: { - shares: true - } - }) - for (const l in logs) { - const log = logs[l] - - const operatorAddress = String(log.operator).toLowerCase() - const strategyAddress = String(log.strategy).toLowerCase() - const shares = log.shares - if (!shares) continue + let foundSharesIndex = operatorShares + .get(operatorAddress) + .findIndex( + (os) => + os.strategyAddress.toLowerCase() === strategyAddress.toLowerCase() + ) + + if (foundSharesIndex !== undefined && foundSharesIndex === -1) { + operatorShares + .get(operatorAddress) + .push({ shares: 0n, strategyAddress: strategyAddress }) + + foundSharesIndex = operatorShares + .get(operatorAddress) + .findIndex( + (os) => + os.strategyAddress.toLowerCase() === + strategyAddress.toLowerCase() + ) + } - // Load existing staker shares data - if (!operatorShares.has(operatorAddress)) { - const foundOperatorInit = operatorInit.find( - (o) => o.address.toLowerCase() === operatorAddress.toLowerCase() - ) - if (foundOperatorInit) { - operatorShares.set( - operatorAddress, - foundOperatorInit.shares.map((o) => ({ - ...o, - shares: BigInt(o.shares) - })) - ) - } else { - operatorShares.set(operatorAddress, []) + if (log.eventName === 'OperatorSharesIncreased') { + operatorShares.get(operatorAddress)[foundSharesIndex].shares = + operatorShares.get(operatorAddress)[foundSharesIndex].shares + + BigInt(shares) + } else if (log.eventName === 'OperatorSharesDecreased') { + operatorShares.get(operatorAddress)[foundSharesIndex].shares = + operatorShares.get(operatorAddress)[foundSharesIndex].shares - + BigInt(shares) + } } - } - - let foundSharesIndex = operatorShares - .get(operatorAddress) - .findIndex( - (os) => - os.strategyAddress.toLowerCase() === strategyAddress.toLowerCase() - ) - - if (foundSharesIndex !== undefined && foundSharesIndex === -1) { - operatorShares - .get(operatorAddress) - .push({ shares: 0n, strategyAddress: strategyAddress }) - - foundSharesIndex = operatorShares - .get(operatorAddress) - .findIndex( - (os) => - os.strategyAddress.toLowerCase() === strategyAddress.toLowerCase() - ) - } - if (log.eventName === 'OperatorSharesIncreased') { - operatorShares.get(operatorAddress)[foundSharesIndex].shares = - operatorShares.get(operatorAddress)[foundSharesIndex].shares + - BigInt(shares) - } else if (log.eventName === 'OperatorSharesDecreased') { - operatorShares.get(operatorAddress)[foundSharesIndex].shares = - operatorShares.get(operatorAddress)[foundSharesIndex].shares - - BigInt(shares) - } - } + console.log(`[Batch] Operator Shares from: ${fromBlock} to: ${toBlock}`) + }, + 100_000n + ) // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index 9d1461f2..8b97d881 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -5,6 +5,7 @@ import { baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, + loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -40,51 +41,57 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { return } - const logs = await prismaClient.eventLogs_OperatorMetadataURIUpdated.findMany( - { - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock + await loopThroughBlocks( + firstBlock, + lastBlock, + async (fromBlock, toBlock) => { + const logs = + await prismaClient.eventLogs_OperatorMetadataURIUpdated.findMany({ + where: { + blockNumber: { + gt: fromBlock, + lte: toBlock + } + } + }) + + for (const l in logs) { + const log = logs[l] + + const operatorAddress = String(log.operator).toLowerCase() + const existingRecord = operatorList.get(operatorAddress) + + const blockNumber = BigInt(log.blockNumber) + const timestamp = log.blockTime + + if (existingRecord) { + // Operator has been registered before in this fetch + operatorList.set(operatorAddress, { + metadataUrl: log.metadataURI, + metadata: defaultMetadata, + isMetadataSynced: false, + createdAtBlock: existingRecord.createdAtBlock, + updatedAtBlock: blockNumber, + createdAt: existingRecord.createdAt, + updatedAt: timestamp + }) + } else { + // Operator being registered for the first time in this fetch + operatorList.set(operatorAddress, { + metadataUrl: log.metadataURI, + metadata: defaultMetadata, + isMetadataSynced: false, + createdAtBlock: blockNumber, // Will be omitted in upsert if operator exists in db + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) } } - } + }, + 100_000n ) - for (const l in logs) { - const log = logs[l] - - const operatorAddress = String(log.operator).toLowerCase() - const existingRecord = operatorList.get(operatorAddress) - - const blockNumber = BigInt(log.blockNumber) - const timestamp = log.blockTime - - if (existingRecord) { - // Operator has been registered before in this fetch - operatorList.set(operatorAddress, { - metadataUrl: log.metadataURI, - metadata: defaultMetadata, - isMetadataSynced: false, - createdAtBlock: existingRecord.createdAtBlock, - updatedAtBlock: blockNumber, - createdAt: existingRecord.createdAt, - updatedAt: timestamp - }) - } else { - // Operator being registered for the first time in this fetch - operatorList.set(operatorAddress, { - metadataUrl: log.metadataURI, - metadata: defaultMetadata, - isMetadataSynced: false, - createdAtBlock: blockNumber, // Will be omitted in upsert if operator exists in db - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } - } - // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index 684097bf..6e4147c7 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -4,6 +4,7 @@ import { baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, + loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -32,34 +33,41 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { return } - const logs = await prismaClient.eventLogs_PodDeployed.findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock - } - } - }) + await loopThroughBlocks( + firstBlock, + lastBlock, + async (fromBlock, toBlock) => { + const logs = await prismaClient.eventLogs_PodDeployed.findMany({ + where: { + blockNumber: { + gt: fromBlock, + lte: toBlock + } + } + }) - for (const l in logs) { - const log = logs[l] + for (const l in logs) { + const log = logs[l] - const podAddress = String(log.eigenPod).toLowerCase() - const podOwner = String(log.podOwner).toLowerCase() + const podAddress = String(log.eigenPod).toLowerCase() + const podOwner = String(log.podOwner).toLowerCase() - const blockNumber = BigInt(log.blockNumber) - const timestamp = log.blockTime + const blockNumber = BigInt(log.blockNumber) + const timestamp = log.blockTime - podList.push({ - address: podAddress, - owner: podOwner, - blockNumber, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } + podList.push({ + address: podAddress, + owner: podOwner, + blockNumber, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) + } + }, + 100_000n + ) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index 1d59f133..d7aa6fc7 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -5,6 +5,7 @@ import { baseBlock, bulkUpdateDbTransactions, fetchLastSyncBlock, + loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -41,179 +42,170 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { await prismaClient.stakerStrategyShares.deleteMany() } - const logsStakerDelegated = await prismaClient.eventLogs_StakerDelegated - .findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock - } - } - }) - .then((logs) => - logs.map((log) => ({ - ...log, - shares: '', - strategy: '', - eventName: 'StakerDelegated' - })) - ) + await loopThroughBlocks( + firstBlock, + lastBlock, + async (fromBlock, toBlock) => { + // biome-ignore lint/suspicious/noExplicitAny: + let allLogs: any[] = [] - const logsStakerUndelegated = await prismaClient.eventLogs_StakerUndelegated - .findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock - } - } - }) - .then((logs) => - logs.map((log) => ({ - ...log, - shares: '', - strategy: '', - eventName: 'StakerUndelegated' - })) - ) + await prismaClient.eventLogs_StakerDelegated + .findMany({ where: { blockNumber: { gt: fromBlock, lte: toBlock } } }) + .then((logs) => { + allLogs = [ + ...allLogs, + ...logs.map((log) => ({ ...log, eventName: 'StakerDelegated' })) + ] + }) - const logsOperatorSharesIncreased = - await prismaClient.eventLogs_OperatorSharesIncreased - .findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock - } - } - }) - .then((logs) => - logs.map((log) => ({ - ...log, - shares: log.shares, - strategy: log.strategy, - eventName: 'OperatorSharesIncreased' - })) - ) + await prismaClient.eventLogs_StakerUndelegated + .findMany({ where: { blockNumber: { gt: fromBlock, lte: toBlock } } }) + .then((logs) => { + allLogs = [ + ...allLogs, + ...logs.map((log) => ({ ...log, eventName: 'StakerUndelegated' })) + ] + }) - const logsOperatorSharesDecreased = - await prismaClient.eventLogs_OperatorSharesDecreased - .findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock - } + await prismaClient.eventLogs_OperatorSharesIncreased + .findMany({ where: { blockNumber: { gt: fromBlock, lte: toBlock } } }) + .then((logs) => { + allLogs = [ + ...allLogs, + ...logs.map((log) => ({ + ...log, + eventName: 'OperatorSharesIncreased' + })) + ] + }) + + await prismaClient.eventLogs_OperatorSharesDecreased + .findMany({ where: { blockNumber: { gt: fromBlock, lte: toBlock } } }) + .then((logs) => { + allLogs = [ + ...allLogs, + ...logs.map((log) => ({ + ...log, + eventName: 'OperatorSharesDecreased' + })) + ] + }) + + // Sort all logs by their block number and log index + allLogs = allLogs.sort((a, b) => { + if (a.blockNumber === b.blockNumber) { + return a.transactionIndex - b.transactionIndex } + + return Number(a.blockNumber - b.blockNumber) }) - .then((logs) => - logs.map((log) => ({ - ...log, - shares: log.shares, - strategy: log.strategy, - eventName: 'OperatorSharesDecreased' - })) - ) - const logs = [ - ...logsStakerDelegated, - ...logsStakerUndelegated, - ...logsOperatorSharesIncreased, - ...logsOperatorSharesDecreased - ] - - // Stakers list - const stakerAddresses = logs.map((l) => String(l.staker).toLowerCase()) - const stakerInit = await prismaClient.staker.findMany({ - where: { address: { in: stakerAddresses } }, - include: { - shares: true - } - }) + // Stakers list + const stakerAddresses = allLogs.map((l) => String(l.staker).toLowerCase()) + const stakerInit = + firstBlock !== baseBlock + ? await prismaClient.staker.findMany({ + where: { address: { in: stakerAddresses } }, + include: { + shares: true + } + }) + : [] - for (const l in logs) { - const log = logs[l] + for (const l in allLogs) { + const log = allLogs[l] - const operatorAddress = String(log.operator).toLowerCase() - const stakerAddress = String(log.staker).toLowerCase() + const operatorAddress = String(log.operator).toLowerCase() + const stakerAddress = String(log.staker).toLowerCase() - const blockNumber = BigInt(log.blockNumber) - const timestamp = log.blockTime + const blockNumber = BigInt(log.blockNumber) + const timestamp = log.blockTime - // Load existing staker shares data - if (!stakers.has(stakerAddress)) { - const foundStakerInit = stakerInit.find( - (s) => s.address.toLowerCase() === stakerAddress.toLowerCase() - ) - if (foundStakerInit) { - // Address not in this set of logs but in db - stakers.set(stakerAddress, { - operatorAddress: foundStakerInit.operatorAddress, - shares: foundStakerInit.shares.map((s) => ({ - ...s, - shares: BigInt(s.shares) - })), - createdAtBlock: foundStakerInit.createdAtBlock, - updatedAtBlock: blockNumber, - createdAt: foundStakerInit.createdAt, - updatedAt: timestamp - }) - } else { - // Address neither in this set of logs nor in db - stakers.set(stakerAddress, { - operatorAddress: null, - shares: [], - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } - } else { - // Address previously found in this set of logs - stakers.get(stakerAddress).updatedAtBlock = blockNumber - stakers.get(stakerAddress).updatedAt = timestamp - } + // Load existing staker shares data + if (!stakers.has(stakerAddress)) { + const foundStakerInit = stakerInit.find( + (s) => s.address.toLowerCase() === stakerAddress.toLowerCase() + ) + if (foundStakerInit) { + // Address not in this set of logs but in db + stakers.set(stakerAddress, { + operatorAddress: foundStakerInit.operatorAddress, + shares: foundStakerInit.shares.map((s) => ({ + ...s, + shares: BigInt(s.shares) + })), + createdAtBlock: foundStakerInit.createdAtBlock, + updatedAtBlock: blockNumber, + createdAt: foundStakerInit.createdAt, + updatedAt: timestamp + }) + } else { + // Address neither in this set of logs nor in db + stakers.set(stakerAddress, { + operatorAddress: null, + shares: [], + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) + } + } else { + // Address previously found in this set of logs + stakers.get(stakerAddress).updatedAtBlock = blockNumber + stakers.get(stakerAddress).updatedAt = timestamp + } - if (log.eventName === 'StakerDelegated') { - stakers.get(stakerAddress).operatorAddress = operatorAddress - } else if (log.eventName === 'StakerUndelegated') { - stakers.get(stakerAddress).operatorAddress = null - } else if ( - log.eventName === 'OperatorSharesIncreased' || - log.eventName === 'OperatorSharesDecreased' - ) { - const strategyAddress = String(log.strategy).toLowerCase() - const shares = BigInt(log.shares) - if (!shares) continue - - let foundSharesIndex = stakers - .get(stakerAddress) - .shares.findIndex( - (ss) => - ss.strategyAddress.toLowerCase() === strategyAddress.toLowerCase() - ) + if (log.eventName === 'StakerDelegated') { + stakers.get(stakerAddress).operatorAddress = operatorAddress + } else if (log.eventName === 'StakerUndelegated') { + stakers.get(stakerAddress).operatorAddress = null + } else if ( + log.eventName === 'OperatorSharesIncreased' || + log.eventName === 'OperatorSharesDecreased' + ) { + const strategyAddress = String(log.strategy).toLowerCase() + const shares = BigInt(log.shares) + if (!shares) continue - if (foundSharesIndex !== undefined && foundSharesIndex === -1) { - stakers.get(stakerAddress).shares.push({ shares: 0n, strategyAddress }) + let foundSharesIndex = stakers + .get(stakerAddress) + .shares.findIndex( + (ss) => + ss.strategyAddress.toLowerCase() === + strategyAddress.toLowerCase() + ) - foundSharesIndex = stakers - .get(stakerAddress) - .shares.findIndex( - (os) => - os.strategyAddress.toLowerCase() === strategyAddress.toLowerCase() - ) - } + if (foundSharesIndex !== undefined && foundSharesIndex === -1) { + stakers + .get(stakerAddress) + .shares.push({ shares: 0n, strategyAddress }) - if (log.eventName === 'OperatorSharesIncreased') { - stakers.get(stakerAddress).shares[foundSharesIndex].shares = - stakers.get(stakerAddress).shares[foundSharesIndex].shares + shares - } else if (log.eventName === 'OperatorSharesDecreased') { - stakers.get(stakerAddress).shares[foundSharesIndex].shares = - stakers.get(stakerAddress).shares[foundSharesIndex].shares - shares + foundSharesIndex = stakers + .get(stakerAddress) + .shares.findIndex( + (os) => + os.strategyAddress.toLowerCase() === + strategyAddress.toLowerCase() + ) + } + + if (log.eventName === 'OperatorSharesIncreased') { + stakers.get(stakerAddress).shares[foundSharesIndex].shares = + stakers.get(stakerAddress).shares[foundSharesIndex].shares + + shares + } else if (log.eventName === 'OperatorSharesDecreased') { + stakers.get(stakerAddress).shares[foundSharesIndex].shares = + stakers.get(stakerAddress).shares[foundSharesIndex].shares - + shares + } + } } - } - } + + console.log(`[Batch] Stakers from: ${fromBlock} to: ${toBlock}`) + }, + 100_000n + ) // biome-ignore lint/suspicious/noExplicitAny: const dbTransactions: any[] = [] diff --git a/packages/seeder/src/seedWithdrawalsCompleted.ts b/packages/seeder/src/seedWithdrawalsCompleted.ts index 0b1a56ff..8c264f16 100644 --- a/packages/seeder/src/seedWithdrawalsCompleted.ts +++ b/packages/seeder/src/seedWithdrawalsCompleted.ts @@ -2,6 +2,7 @@ import { getPrismaClient } from './utils/prismaClient' import { bulkUpdateDbTransactions, fetchLastSyncBlock, + loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -35,24 +36,31 @@ export async function seedCompletedWithdrawals( return } - const logs = await prismaClient.eventLogs_WithdrawalCompleted.findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock - } - } - }) + await loopThroughBlocks( + firstBlock, + lastBlock, + async (fromBlock, toBlock) => { + const logs = await prismaClient.eventLogs_WithdrawalCompleted.findMany({ + where: { + blockNumber: { + gt: fromBlock, + lte: toBlock + } + } + }) - for (const l in logs) { - const log = logs[l] + for (const l in logs) { + const log = logs[l] - const withdrawalRoot = log.withdrawalRoot + const withdrawalRoot = log.withdrawalRoot - if (withdrawalRoot) { - completedWithdrawalList.push(withdrawalRoot) - } - } + if (withdrawalRoot) { + completedWithdrawalList.push(withdrawalRoot) + } + } + }, + 100_000n + ) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedWithdrawalsQueued.ts b/packages/seeder/src/seedWithdrawalsQueued.ts index 3a109825..52661864 100644 --- a/packages/seeder/src/seedWithdrawalsQueued.ts +++ b/packages/seeder/src/seedWithdrawalsQueued.ts @@ -3,6 +3,7 @@ import { getPrismaClient } from './utils/prismaClient' import { bulkUpdateDbTransactions, fetchLastSyncBlock, + loopThroughBlocks, saveLastSyncBlock } from './utils/seeder' @@ -30,50 +31,59 @@ export async function seedQueuedWithdrawals( // Bail early if there is no block diff to sync if (lastBlock - firstBlock <= 0) { - console.log(`[In Sync] [Data] Queued Withdrawal from: ${firstBlock} to: ${lastBlock}`) + console.log( + `[In Sync] [Data] Queued Withdrawal from: ${firstBlock} to: ${lastBlock}` + ) return } - const logs = await prismaClient.eventLogs_WithdrawalQueued.findMany({ - where: { - blockNumber: { - gt: firstBlock, - lte: lastBlock - } - } - }) + await loopThroughBlocks( + firstBlock, + lastBlock, + async (fromBlock, toBlock) => { + const logs = await prismaClient.eventLogs_WithdrawalQueued.findMany({ + where: { + blockNumber: { + gt: fromBlock, + lte: toBlock + } + } + }) - for (const l in logs) { - const log = logs[l] + for (const l in logs) { + const log = logs[l] - const withdrawalRoot = log.withdrawalRoot + const withdrawalRoot = log.withdrawalRoot - const blockNumber = BigInt(log.blockNumber) - const timestamp = log.blockTime + const blockNumber = BigInt(log.blockNumber) + const timestamp = log.blockTime - if (withdrawalRoot) { - const stakerAddress = log.staker.toLowerCase() - const delegatedTo = log.delegatedTo.toLowerCase() - const withdrawerAddress = log.withdrawer.toLowerCase() + if (withdrawalRoot) { + const stakerAddress = log.staker.toLowerCase() + const delegatedTo = log.delegatedTo.toLowerCase() + const withdrawerAddress = log.withdrawer.toLowerCase() - queuedWithdrawalList.push({ - withdrawalRoot, - nonce: Number(log.nonce), - isCompleted: false, - stakerAddress, - delegatedTo, - withdrawerAddress, - strategies: log.strategies.map((s) => s.toLowerCase()) as string[], - shares: log.shares.map((s) => s.toString()), + queuedWithdrawalList.push({ + withdrawalRoot, + nonce: Number(log.nonce), + isCompleted: false, + stakerAddress, + delegatedTo, + withdrawerAddress, + strategies: log.strategies.map((s) => s.toLowerCase()) as string[], + shares: log.shares.map((s) => s.toString()), - startBlock: log.startBlock, - createdAtBlock: blockNumber, - updatedAtBlock: blockNumber, - createdAt: timestamp, - updatedAt: timestamp - }) - } - } + startBlock: log.startBlock, + createdAtBlock: blockNumber, + updatedAtBlock: blockNumber, + createdAt: timestamp, + updatedAt: timestamp + }) + } + } + }, + 100_000n + ) // Prepare db transaction object // biome-ignore lint/suspicious/noExplicitAny: @@ -88,7 +98,10 @@ export async function seedQueuedWithdrawals( ) } - await bulkUpdateDbTransactions(dbTransactions, `[Data] Queued Withdrawal from: ${firstBlock} to: ${lastBlock} size: ${queuedWithdrawalList.length}`) + await bulkUpdateDbTransactions( + dbTransactions, + `[Data] Queued Withdrawal from: ${firstBlock} to: ${lastBlock} size: ${queuedWithdrawalList.length}` + ) // // Storing last sycned block await saveLastSyncBlock(blockSyncKey, lastBlock) From 4f54314e24258d52543b9d8c86b0ce3345ab1487 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Tue, 11 Jun 2024 01:50:30 +0530 Subject: [PATCH 56/62] Lower batch sizes --- packages/seeder/src/seedAvs.ts | 2 +- packages/seeder/src/seedAvsOperators.ts | 2 +- packages/seeder/src/seedOperatorShares.ts | 2 +- packages/seeder/src/seedOperators.ts | 2 +- packages/seeder/src/seedPods.ts | 2 +- packages/seeder/src/seedStakers.ts | 2 +- packages/seeder/src/seedWithdrawalsCompleted.ts | 2 +- packages/seeder/src/seedWithdrawalsQueued.ts | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/seeder/src/seedAvs.ts b/packages/seeder/src/seedAvs.ts index fe007bde..a74b65e4 100644 --- a/packages/seeder/src/seedAvs.ts +++ b/packages/seeder/src/seedAvs.ts @@ -88,7 +88,7 @@ export async function seedAvs(toBlock?: bigint, fromBlock?: bigint) { } } }, - 100_000n + 10_000n ) // Prepare db transaction object diff --git a/packages/seeder/src/seedAvsOperators.ts b/packages/seeder/src/seedAvsOperators.ts index 9661ccda..af0deb1f 100644 --- a/packages/seeder/src/seedAvsOperators.ts +++ b/packages/seeder/src/seedAvsOperators.ts @@ -65,7 +65,7 @@ export async function seedAvsOperators(toBlock?: bigint, fromBlock?: bigint) { } } }, - 100_000n + 10_000n ) // Prepare db transaction object diff --git a/packages/seeder/src/seedOperatorShares.ts b/packages/seeder/src/seedOperatorShares.ts index 5009f982..5c6808af 100644 --- a/packages/seeder/src/seedOperatorShares.ts +++ b/packages/seeder/src/seedOperatorShares.ts @@ -150,7 +150,7 @@ export async function seedOperatorShares(toBlock?: bigint, fromBlock?: bigint) { console.log(`[Batch] Operator Shares from: ${fromBlock} to: ${toBlock}`) }, - 100_000n + 10_000n ) // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedOperators.ts b/packages/seeder/src/seedOperators.ts index 8b97d881..39bca794 100644 --- a/packages/seeder/src/seedOperators.ts +++ b/packages/seeder/src/seedOperators.ts @@ -89,7 +89,7 @@ export async function seedOperators(toBlock?: bigint, fromBlock?: bigint) { } } }, - 100_000n + 10_000n ) // Prepare db transaction object diff --git a/packages/seeder/src/seedPods.ts b/packages/seeder/src/seedPods.ts index 6e4147c7..ad1c1b85 100644 --- a/packages/seeder/src/seedPods.ts +++ b/packages/seeder/src/seedPods.ts @@ -66,7 +66,7 @@ export async function seedPods(toBlock?: bigint, fromBlock?: bigint) { }) } }, - 100_000n + 10_000n ) // Prepare db transaction object diff --git a/packages/seeder/src/seedStakers.ts b/packages/seeder/src/seedStakers.ts index d7aa6fc7..11e33cb2 100644 --- a/packages/seeder/src/seedStakers.ts +++ b/packages/seeder/src/seedStakers.ts @@ -204,7 +204,7 @@ export async function seedStakers(toBlock?: bigint, fromBlock?: bigint) { console.log(`[Batch] Stakers from: ${fromBlock} to: ${toBlock}`) }, - 100_000n + 10_000n ) // biome-ignore lint/suspicious/noExplicitAny: diff --git a/packages/seeder/src/seedWithdrawalsCompleted.ts b/packages/seeder/src/seedWithdrawalsCompleted.ts index 8c264f16..d3b82671 100644 --- a/packages/seeder/src/seedWithdrawalsCompleted.ts +++ b/packages/seeder/src/seedWithdrawalsCompleted.ts @@ -59,7 +59,7 @@ export async function seedCompletedWithdrawals( } } }, - 100_000n + 10_000n ) // Prepare db transaction object diff --git a/packages/seeder/src/seedWithdrawalsQueued.ts b/packages/seeder/src/seedWithdrawalsQueued.ts index 52661864..5e7c026b 100644 --- a/packages/seeder/src/seedWithdrawalsQueued.ts +++ b/packages/seeder/src/seedWithdrawalsQueued.ts @@ -82,7 +82,7 @@ export async function seedQueuedWithdrawals( } } }, - 100_000n + 10_000n ) // Prepare db transaction object From 4e23855edebe9b189e344eecb5e6db388d59e083 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Tue, 11 Jun 2024 01:52:35 +0530 Subject: [PATCH 57/62] Re-Enable monitor --- packages/seeder/src/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index d7b3bffd..ca412f6e 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -73,7 +73,6 @@ async function seedEigenPodValidators() { try { console.log('\nSeeding Eigen Pods data ...') - await seedPods() await seedValidators() } catch (error) { console.log('Failed to seed Validators at block:', Date.now()) @@ -103,4 +102,4 @@ async function monitorMetadata() { seedEigenDataLoop() // seedEigenPodValidators() -// monitorMetadata() +monitorMetadata() From e5bc12ac4ad7bfb10a02abb02879c95079dec50a Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Tue, 11 Jun 2024 02:04:51 +0530 Subject: [PATCH 58/62] Update validator indexer logs --- packages/seeder/src/seedValidators.ts | 31 +++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/packages/seeder/src/seedValidators.ts b/packages/seeder/src/seedValidators.ts index 1f4863fb..3d55972c 100644 --- a/packages/seeder/src/seedValidators.ts +++ b/packages/seeder/src/seedValidators.ts @@ -16,7 +16,10 @@ export async function seedValidators(shouldClearPrev?: boolean) { }) const podAddressList = podAddresses.map((p) => p.address.toLowerCase()) - const lastValidatorIndex = await prismaClient.validator.findFirst({ select: { validatorIndex: true }, orderBy: { validatorIndex: 'desc' }}) + const lastValidatorIndex = await prismaClient.validator.findFirst({ + select: { validatorIndex: true }, + orderBy: { validatorIndex: 'desc' } + }) const rpcUrl = process.env.NETWORK_CHAIN_RPC_URL const status = 'finalized' @@ -26,10 +29,17 @@ export async function seedValidators(shouldClearPrev?: boolean) { let isAtEnd = false let batchIndex = 0 - let currentIndex = (!shouldClearPrev && lastValidatorIndex) ? Number(lastValidatorIndex.validatorIndex) + 1 : 0 + let currentIndex = + !shouldClearPrev && lastValidatorIndex + ? Number(lastValidatorIndex.validatorIndex) + 1 + : 0 const chunkSize = 8000 const batchSize = 120_000 - const clearPerv = shouldClearPrev ? shouldClearPrev : lastValidatorIndex?.validatorIndex ? false: true + const clearPerv = shouldClearPrev + ? shouldClearPrev + : lastValidatorIndex?.validatorIndex + ? false + : true while (!isAtEnd) { const validatorRestakeIds = Array.from( @@ -39,7 +49,9 @@ export async function seedValidators(shouldClearPrev?: boolean) { const chunks = chunkArray(validatorRestakeIds, chunkSize) console.log( - `Batch ${batchIndex} from ${currentIndex} - ${currentIndex + batchSize}` + `[Batch] Validator chunk ${batchIndex} from ${currentIndex} - ${ + currentIndex + batchSize + }` ) await Promise.allSettled( @@ -73,12 +85,6 @@ export async function seedValidators(shouldClearPrev?: boolean) { } }) - console.log( - `Batch ${batchIndex} chunk received ${i}`, - validatorsData.data.length, - validators.length - ) - if (validatorsData.data.length < chunkSize) { isAtEnd = true } @@ -103,7 +109,10 @@ export async function seedValidators(shouldClearPrev?: boolean) { }) ) - await bulkUpdateDbTransactions(dbTransactions) + await bulkUpdateDbTransactions( + dbTransactions, + `[Data] Validator updated size: ${podValidators.length}` + ) console.log('Seeded Validators', podValidators.length) console.timeEnd('Done in') From ccbfd53487e23fda407da576e51e80ba6f8d8443 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Tue, 11 Jun 2024 02:05:06 +0530 Subject: [PATCH 59/62] Re-Enable monitor and validator logs --- packages/seeder/src/index.ts | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/seeder/src/index.ts b/packages/seeder/src/index.ts index ca412f6e..ff784af7 100644 --- a/packages/seeder/src/index.ts +++ b/packages/seeder/src/index.ts @@ -66,40 +66,40 @@ async function seedEigenDataLoop() { } } -async function seedEigenPodValidators() { - await delay(120) +async function monitorMetadata() { + await delay(60) while (true) { try { - console.log('\nSeeding Eigen Pods data ...') + console.log('\nMonitoring metadata...') - await seedValidators() + await monitorAvsMetadata() + await monitorOperatorMetadata() } catch (error) { - console.log('Failed to seed Validators at block:', Date.now()) - console.log(error) + console.log('Failed to monitor metadata at:', Date.now()) } - await delay(600) + await delay(120) } } -async function monitorMetadata() { +async function seedEigenPodValidators() { await delay(120) - + while (true) { try { - console.log('\nMonitoring metadata...') + console.log('\nSeeding Eigen Pods data ...') - await monitorAvsMetadata() - await monitorOperatorMetadata() + await seedValidators() } catch (error) { - console.log('Failed to monitor metadata at: ', Date.now()) + console.log(error) + console.log('Failed to seed Validators at:', Date.now()) } - await delay(420) + await delay(3600) } } seedEigenDataLoop() -// seedEigenPodValidators() monitorMetadata() +seedEigenPodValidators() From 9fd77077c6231f0db50092a35aa4bd91bede1fa1 Mon Sep 17 00:00:00 2001 From: Udit <25996904+uditdc@users.noreply.github.com> Date: Tue, 11 Jun 2024 02:57:59 +0530 Subject: [PATCH 60/62] Pass CI build version as the API version, displayed in routes --- .github/workflows/build_publish.yml | 8 +++++--- Dockerfile-API | 3 +++ packages/api/src/routes/index.ts | 5 +++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_publish.yml b/.github/workflows/build_publish.yml index d0968295..263712e4 100644 --- a/.github/workflows/build_publish.yml +++ b/.github/workflows/build_publish.yml @@ -41,13 +41,13 @@ jobs: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - + - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}${{ matrix.image }} - + - name: install modules run: npm i @@ -58,4 +58,6 @@ jobs: file: ${{ matrix.dockerfile }} push: true tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file + labels: ${{ steps.meta.outputs.labels }} + build-args: | + CI_BUILD_VERSION=${{ github.ref_name }} diff --git a/Dockerfile-API b/Dockerfile-API index c842f02c..11c13a99 100644 --- a/Dockerfile-API +++ b/Dockerfile-API @@ -2,6 +2,9 @@ FROM node:18 WORKDIR /app +ARG CI_BUILD_VERSION +ENV API_VERSION=$CI_BUILD_VERSION + COPY ./packages/api/package*.json ./ RUN npm install diff --git a/packages/api/src/routes/index.ts b/packages/api/src/routes/index.ts index bbf9d27e..6550214c 100644 --- a/packages/api/src/routes/index.ts +++ b/packages/api/src/routes/index.ts @@ -12,6 +12,11 @@ const apiRouter = express.Router() // Health route apiRouter.get('/health', (_, res) => res.send({ status: 'ok' })) +// Version route +apiRouter.get('/version', (_, res) => + res.send({ version: process.env.API_VERSION || 'development' }) +) + // Remaining routes apiRouter.use('/avs', avsRoutes) apiRouter.use('/strategies', strategiesRoutes) From d016dc71897c4571eee4be5beca514fc84a59ab0 Mon Sep 17 00:00:00 2001 From: Liam Zhang Date: Sun, 16 Jun 2024 23:24:02 +0800 Subject: [PATCH 61/62] update api to v0.0.32 --- packages/openapi/openapi.json | 884 +++++++++++++++--- .../src/apiResponseSchema/avs/avsResponse.ts | 4 + .../base/strategyTvlResponse.ts | 19 + .../apiResponseSchema/base/tvlResponses.ts | 5 +- .../metrics/summaryMetricsResponse.ts | 6 +- .../src/apiResponseSchema/operatorResponse.ts | 4 + .../src/apiResponseSchema/stakerResponse.ts | 36 +- packages/openapi/src/documentBase.ts | 2 + .../src/routes/avs/getAvsStakersByAddress.ts | 8 +- .../src/routes/metrics/getTvlRestaking.ts | 6 +- .../src/routes/operators/getAllOperators.ts | 2 +- .../src/routes/stakers/getAllStakers.ts | 39 + .../stakers/getCompletedStakerWithdrawals.ts | 3 +- .../stakers/getQueuedStakerWithdrawals.ts | 3 +- .../getQueuedWithdrawableStakerWithdrawals.ts | 3 +- .../src/routes/stakers/getStakerByAddress.ts | 34 + .../routes/stakers/getStakerWithdrawals.ts | 3 +- packages/openapi/src/routes/stakers/index.ts | 4 + .../openapi/src/routes/system/getHealth.ts | 27 + .../openapi/src/routes/system/getVersion.ts | 27 + packages/openapi/src/routes/system/index.ts | 10 + 21 files changed, 990 insertions(+), 139 deletions(-) create mode 100644 packages/openapi/src/routes/stakers/getAllStakers.ts create mode 100644 packages/openapi/src/routes/stakers/getStakerByAddress.ts create mode 100644 packages/openapi/src/routes/system/getHealth.ts create mode 100644 packages/openapi/src/routes/system/getVersion.ts create mode 100644 packages/openapi/src/routes/system/index.ts diff --git a/packages/openapi/openapi.json b/packages/openapi/openapi.json index f5135eb3..6bd516af 100644 --- a/packages/openapi/openapi.json +++ b/packages/openapi/openapi.json @@ -16,6 +16,70 @@ } ], "paths": { + "/version": { + "get": { + "operationId": "getVersion", + "summary": "Retrieve API server version", + "description": "Returns API server version.", + "tags": [ + "System" + ], + "responses": { + "200": { + "description": "The API server version.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "version": { + "type": "string", + "description": "The version of the API server", + "example": "v0.0.1" + } + }, + "required": [ + "version" + ] + } + } + } + } + } + } + }, + "/health": { + "get": { + "operationId": "getHealth", + "summary": "Retrieve API server status", + "description": "Returns API server status.", + "tags": [ + "System" + ], + "responses": { + "200": { + "description": "The API server status.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "The status of the API server", + "example": "ok" + } + }, + "required": [ + "status" + ] + } + } + } + } + } + } + }, "/metrics": { "get": { "operationId": "getAllMetrics", @@ -55,6 +119,19 @@ "stETH": 2000000 } }, + "tvlStrategiesEth": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in ETH", + "example": 1000000 + }, + "description": "The total value locked (TVL) in each restaking strategy, denominated in ETH", + "example": { + "cbETH": 1000000, + "stETH": 2000000 + } + }, "tvlBeaconChain": { "type": "number", "description": "The total value locked (TVL) in ETH in the beacon chain ETH strategy", @@ -80,6 +157,7 @@ "tvl", "tvlRestaking", "tvlStrategies", + "tvlStrategiesEth", "tvlBeaconChain", "totalAVS", "totalOperators", @@ -252,11 +330,25 @@ "cbETH": 1000000, "stETH": 2000000 } + }, + "tvlStrategiesEth": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in ETH", + "example": 1000000 + }, + "description": "The total value locked (TVL) in each restaking strategy, denominated in ETH", + "example": { + "cbETH": 1000000, + "stETH": 2000000 + } } }, "required": [ "tvl", - "tvlStrategies" + "tvlStrategies", + "tvlStrategiesEth" ] } } @@ -712,6 +804,19 @@ "Eigen": 1000000, "cbETH": 2000000 } + }, + "tvlStrategiesEth": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in ETH", + "example": 1000000 + }, + "description": "The TVL of each individual restaking strategy in ETH", + "example": { + "Eigen": 1000000, + "cbETH": 2000000 + } } }, "required": [ @@ -719,7 +824,8 @@ "tvlBeaconChain", "tvlRestaking", "tvlWETH", - "tvlStrategies" + "tvlStrategies", + "tvlStrategiesEth" ], "description": "The total value locked (TVL) in the AVS", "example": { @@ -730,6 +836,10 @@ "tvlStrategies": { "Eigen": 1000000, "cbETH": 2000000 + }, + "tvlStrategiesEth": { + "stETH": 1000000, + "cbETH": 2000000 } } } @@ -1111,6 +1221,19 @@ "Eigen": 1000000, "cbETH": 2000000 } + }, + "tvlStrategiesEth": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in ETH", + "example": 1000000 + }, + "description": "The TVL of each individual restaking strategy in ETH", + "example": { + "Eigen": 1000000, + "cbETH": 2000000 + } } }, "required": [ @@ -1118,7 +1241,8 @@ "tvlBeaconChain", "tvlRestaking", "tvlWETH", - "tvlStrategies" + "tvlStrategies", + "tvlStrategiesEth" ], "description": "The total value locked (TVL) in the AVS", "example": { @@ -1129,6 +1253,10 @@ "tvlStrategies": { "Eigen": 1000000, "cbETH": 2000000 + }, + "tvlStrategiesEth": { + "stETH": 1000000, + "cbETH": 2000000 } } } @@ -1192,6 +1320,21 @@ }, "required": true }, + { + "in": "query", + "name": "withTvl", + "description": "Toggle whether the route should calculate the TVL from shares", + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ], + "default": "false", + "description": "Toggle whether the route should calculate the TVL from shares", + "example": "false" + } + }, { "in": "query", "name": "skip", @@ -1271,16 +1414,84 @@ } }, "tvl": { - "type": "number", - "description": "The total value locked in the AVS staker", - "example": 0.040888428658906045 + "type": "object", + "properties": { + "tvl": { + "type": "number", + "description": "The combined TVL of all restaking strategies in ETH", + "example": 1000000 + }, + "tvlBeaconChain": { + "type": "number", + "description": "The TVL of Beacon Chain restaking strategy in ETH", + "example": 1000000 + }, + "tvlRestaking": { + "type": "number", + "description": "The combined TVL of all liquid restaking strategies in ETH", + "example": 1000000 + }, + "tvlWETH": { + "type": "number", + "description": "The TVL of WETH restaking strategy in ETH", + "example": 1000000 + }, + "tvlStrategies": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in the strategy's native token", + "example": 1000000 + }, + "description": "The TVL of each individual restaking strategy in its native token", + "example": { + "Eigen": 1000000, + "cbETH": 2000000 + } + }, + "tvlStrategiesEth": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in ETH", + "example": 1000000 + }, + "description": "The TVL of each individual restaking strategy in ETH", + "example": { + "Eigen": 1000000, + "cbETH": 2000000 + } + } + }, + "required": [ + "tvl", + "tvlBeaconChain", + "tvlRestaking", + "tvlWETH", + "tvlStrategies", + "tvlStrategiesEth" + ], + "description": "The total value locked (TVL) in the AVS staker", + "example": { + "tvl": 1000000, + "tvlBeaconChain": 1000000, + "tvlWETH": 1000000, + "tvlRestaking": 1000000, + "tvlStrategies": { + "Eigen": 1000000, + "cbETH": 2000000 + }, + "tvlStrategiesEth": { + "stETH": 1000000, + "cbETH": 2000000 + } + } } }, "required": [ "address", "operatorAddress", - "shares", - "tvl" + "shares" ] } }, @@ -1536,6 +1747,19 @@ "Eigen": 1000000, "cbETH": 2000000 } + }, + "tvlStrategiesEth": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in ETH", + "example": 1000000 + }, + "description": "The TVL of each individual restaking strategy in ETH", + "example": { + "Eigen": 1000000, + "cbETH": 2000000 + } } }, "required": [ @@ -1543,7 +1767,8 @@ "tvlBeaconChain", "tvlRestaking", "tvlWETH", - "tvlStrategies" + "tvlStrategies", + "tvlStrategiesEth" ], "description": "The total value locked (TVL) in the AVS operator", "example": { @@ -1554,6 +1779,10 @@ "tvlStrategies": { "Eigen": 1000000, "cbETH": 2000000 + }, + "tvlStrategiesEth": { + "stETH": 1000000, + "cbETH": 2000000 } } } @@ -1679,7 +1908,7 @@ ], "responses": { "200": { - "description": "The list of Operators records.", + "description": "The list of operator records.", "content": { "application/json": { "schema": { @@ -1815,6 +2044,19 @@ "Eigen": 1000000, "cbETH": 2000000 } + }, + "tvlStrategiesEth": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in ETH", + "example": 1000000 + }, + "description": "The TVL of each individual restaking strategy in ETH", + "example": { + "Eigen": 1000000, + "cbETH": 2000000 + } } }, "required": [ @@ -1822,7 +2064,8 @@ "tvlBeaconChain", "tvlRestaking", "tvlWETH", - "tvlStrategies" + "tvlStrategies", + "tvlStrategiesEth" ], "description": "The total value locked (TVL) in the AVS operator", "example": { @@ -1833,6 +2076,10 @@ "tvlStrategies": { "Eigen": 1000000, "cbETH": 2000000 + }, + "tvlStrategiesEth": { + "stETH": 1000000, + "cbETH": 2000000 } } } @@ -2079,6 +2326,19 @@ "Eigen": 1000000, "cbETH": 2000000 } + }, + "tvlStrategiesEth": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in ETH", + "example": 1000000 + }, + "description": "The TVL of each individual restaking strategy in ETH", + "example": { + "Eigen": 1000000, + "cbETH": 2000000 + } } }, "required": [ @@ -2086,7 +2346,8 @@ "tvlBeaconChain", "tvlRestaking", "tvlWETH", - "tvlStrategies" + "tvlStrategies", + "tvlStrategiesEth" ], "description": "The total value locked (TVL) in the AVS operator", "example": { @@ -2097,6 +2358,10 @@ "tvlStrategies": { "Eigen": 1000000, "cbETH": 2000000 + }, + "tvlStrategiesEth": { + "stETH": 1000000, + "cbETH": 2000000 } } } @@ -2527,64 +2792,56 @@ } } }, - "/stakers/{address}/withdrawals": { + "/stakers": { "get": { - "operationId": "getStakerWithdrawals", - "summary": "Retrieve all withdrawals by staker address", - "description": "Returns all withdrawal data of the requested staker, including the withdrawal root, nonce, withdrawal status, and other relevant information.", + "operationId": "getAllStakers", + "summary": "Retrieve all stakers", + "description": "Returns all staker records. This endpoint supports pagination.", "tags": [ "Stakers" ], "parameters": [ - { - "in": "path", - "name": "address", - "description": "The address of the staker", - "schema": { - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "description": "The address of the staker", - "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" - }, - "required": true - }, { "in": "query", - "name": "total", - "description": "Total number of records in the database", + "name": "withTvl", + "description": "Toggle whether the route should calculate the TVL from shares", "schema": { - "type": "number", - "description": "Total number of records in the database", - "example": 30 - }, - "required": true + "type": "string", + "enum": [ + "true", + "false" + ], + "default": "false", + "description": "Toggle whether the route should calculate the TVL from shares", + "example": "false" + } }, { "in": "query", "name": "skip", - "description": "The number of skiped records for this query", + "description": "The number of records to skip for pagination", "schema": { - "type": "number", - "description": "The number of skiped records for this query", + "type": "string", + "default": "0", + "description": "The number of records to skip for pagination", "example": 0 - }, - "required": true + } }, { "in": "query", "name": "take", - "description": "The number of records returned for this query", + "description": "The number of records to return for pagination", "schema": { - "type": "number", - "description": "The number of records returned for this query", + "type": "string", + "default": "12", + "description": "The number of records to return for pagination", "example": 12 - }, - "required": true + } } ], "responses": { "200": { - "description": "The list of withdrawals.", + "description": "The list of staker records.", "content": { "application/json": { "schema": { @@ -2595,11 +2852,445 @@ "items": { "type": "object", "properties": { - "withdrawalRoot": { + "address": { "type": "string", - "description": "The root hash of the withdrawal", - "example": "0x9e6728ef0a8ad6009107a886047aae35bc5ed7deaa68580b0d1f8f67e3e5ed31" - }, + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the staker", + "example": "0x0000006c21964af0d420af8992851a30fa13a68b" + }, + "operatorAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the operator", + "example": "0x71c6f7ed8c2d4925d0baf16f6a85bb1736d412eb" + }, + "shares": { + "type": "array", + "items": { + "type": "object", + "properties": { + "stakerAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the staker", + "example": "0x0000006c21964af0d420af8992851a30fa13c68a" + }, + "strategyAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the restaking strategy", + "example": "0x93c4b944d05dfe6df7645a86cd2206016c51564a" + }, + "shares": { + "type": "string", + "description": "The amount of shares held in the strategy", + "example": "40888428658906049" + } + }, + "required": [ + "stakerAddress", + "strategyAddress", + "shares" + ] + } + }, + "tvl": { + "type": "object", + "properties": { + "tvl": { + "type": "number", + "description": "The combined TVL of all restaking strategies in ETH", + "example": 1000000 + }, + "tvlBeaconChain": { + "type": "number", + "description": "The TVL of Beacon Chain restaking strategy in ETH", + "example": 1000000 + }, + "tvlRestaking": { + "type": "number", + "description": "The combined TVL of all liquid restaking strategies in ETH", + "example": 1000000 + }, + "tvlWETH": { + "type": "number", + "description": "The TVL of WETH restaking strategy in ETH", + "example": 1000000 + }, + "tvlStrategies": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in the strategy's native token", + "example": 1000000 + }, + "description": "The TVL of each individual restaking strategy in its native token", + "example": { + "Eigen": 1000000, + "cbETH": 2000000 + } + }, + "tvlStrategiesEth": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in ETH", + "example": 1000000 + }, + "description": "The TVL of each individual restaking strategy in ETH", + "example": { + "Eigen": 1000000, + "cbETH": 2000000 + } + } + }, + "required": [ + "tvl", + "tvlBeaconChain", + "tvlRestaking", + "tvlWETH", + "tvlStrategies", + "tvlStrategiesEth" + ], + "description": "The total value locked (TVL) in the AVS staker", + "example": { + "tvl": 1000000, + "tvlBeaconChain": 1000000, + "tvlWETH": 1000000, + "tvlRestaking": 1000000, + "tvlStrategies": { + "Eigen": 1000000, + "cbETH": 2000000 + }, + "tvlStrategiesEth": { + "stETH": 1000000, + "cbETH": 2000000 + } + } + } + }, + "required": [ + "address", + "operatorAddress", + "shares" + ] + } + }, + "meta": { + "type": "object", + "properties": { + "total": { + "type": "number", + "description": "Total number of records in the database", + "example": 30 + }, + "skip": { + "type": "number", + "description": "The number of skiped records for this query", + "example": 0 + }, + "take": { + "type": "number", + "description": "The number of records returned for this query", + "example": 12 + } + }, + "required": [ + "total", + "skip", + "take" + ] + } + }, + "required": [ + "data", + "meta" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/400" + }, + "401": { + "$ref": "#/components/responses/401" + }, + "403": { + "$ref": "#/components/responses/403" + }, + "404": { + "$ref": "#/components/responses/404" + }, + "422": { + "$ref": "#/components/responses/422" + }, + "429": { + "$ref": "#/components/responses/429" + }, + "500": { + "$ref": "#/components/responses/500" + } + } + } + }, + "/stakers/{address}": { + "get": { + "operationId": "getStakerByAddress", + "summary": "Retrieve a staker by address", + "description": "Returns a staker record by address.", + "tags": [ + "Stakers" + ], + "parameters": [ + { + "in": "path", + "name": "address", + "description": "The address of the staker", + "schema": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the staker", + "example": "0x00107cfdeaddc0a3160ed2f6fedd627f313e7b1b" + }, + "required": true + }, + { + "in": "query", + "name": "withTvl", + "description": "Toggle whether the route should calculate the TVL from shares", + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ], + "default": "false", + "description": "Toggle whether the route should calculate the TVL from shares", + "example": "false" + } + } + ], + "responses": { + "200": { + "description": "The record of the requested operator.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "address": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the staker", + "example": "0x0000006c21964af0d420af8992851a30fa13a68b" + }, + "operatorAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the operator", + "example": "0x71c6f7ed8c2d4925d0baf16f6a85bb1736d412eb" + }, + "shares": { + "type": "array", + "items": { + "type": "object", + "properties": { + "stakerAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the staker", + "example": "0x0000006c21964af0d420af8992851a30fa13c68a" + }, + "strategyAddress": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The contract address of the restaking strategy", + "example": "0x93c4b944d05dfe6df7645a86cd2206016c51564a" + }, + "shares": { + "type": "string", + "description": "The amount of shares held in the strategy", + "example": "40888428658906049" + } + }, + "required": [ + "stakerAddress", + "strategyAddress", + "shares" + ] + } + }, + "tvl": { + "type": "object", + "properties": { + "tvl": { + "type": "number", + "description": "The combined TVL of all restaking strategies in ETH", + "example": 1000000 + }, + "tvlBeaconChain": { + "type": "number", + "description": "The TVL of Beacon Chain restaking strategy in ETH", + "example": 1000000 + }, + "tvlRestaking": { + "type": "number", + "description": "The combined TVL of all liquid restaking strategies in ETH", + "example": 1000000 + }, + "tvlWETH": { + "type": "number", + "description": "The TVL of WETH restaking strategy in ETH", + "example": 1000000 + }, + "tvlStrategies": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in the strategy's native token", + "example": 1000000 + }, + "description": "The TVL of each individual restaking strategy in its native token", + "example": { + "Eigen": 1000000, + "cbETH": 2000000 + } + }, + "tvlStrategiesEth": { + "type": "object", + "additionalProperties": { + "type": "number", + "description": "The total value locked (TVL) in the strategy, denominated in ETH", + "example": 1000000 + }, + "description": "The TVL of each individual restaking strategy in ETH", + "example": { + "Eigen": 1000000, + "cbETH": 2000000 + } + } + }, + "required": [ + "tvl", + "tvlBeaconChain", + "tvlRestaking", + "tvlWETH", + "tvlStrategies", + "tvlStrategiesEth" + ], + "description": "The total value locked (TVL) in the AVS staker", + "example": { + "tvl": 1000000, + "tvlBeaconChain": 1000000, + "tvlWETH": 1000000, + "tvlRestaking": 1000000, + "tvlStrategies": { + "Eigen": 1000000, + "cbETH": 2000000 + }, + "tvlStrategiesEth": { + "stETH": 1000000, + "cbETH": 2000000 + } + } + } + }, + "required": [ + "address", + "operatorAddress", + "shares" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/400" + }, + "401": { + "$ref": "#/components/responses/401" + }, + "403": { + "$ref": "#/components/responses/403" + }, + "404": { + "$ref": "#/components/responses/404" + }, + "422": { + "$ref": "#/components/responses/422" + }, + "429": { + "$ref": "#/components/responses/429" + }, + "500": { + "$ref": "#/components/responses/500" + } + } + } + }, + "/stakers/{address}/withdrawals": { + "get": { + "operationId": "getStakerWithdrawals", + "summary": "Retrieve all withdrawals by staker address", + "description": "Returns all withdrawal data of the requested staker, including the withdrawal root, nonce, withdrawal status, and other relevant information.", + "tags": [ + "Stakers" + ], + "parameters": [ + { + "in": "path", + "name": "address", + "description": "The address of the staker", + "schema": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the staker", + "example": "0x74ede5f75247fbdb9266d2b3a7be63b3db7611dd" + }, + "required": true + }, + { + "in": "query", + "name": "skip", + "description": "The number of records to skip for pagination", + "schema": { + "type": "string", + "default": "0", + "description": "The number of records to skip for pagination", + "example": 0 + } + }, + { + "in": "query", + "name": "take", + "description": "The number of records to return for pagination", + "schema": { + "type": "string", + "default": "12", + "description": "The number of records to return for pagination", + "example": 12 + } + } + ], + "responses": { + "200": { + "description": "The list of withdrawals.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "withdrawalRoot": { + "type": "string", + "description": "The root hash of the withdrawal", + "example": "0x9e6728ef0a8ad6009107a886047aae35bc5ed7deaa68580b0d1f8f67e3e5ed31" + }, "nonce": { "type": "number", "description": "The nonce of the withdrawal", @@ -2764,38 +3455,27 @@ }, "required": true }, - { - "in": "query", - "name": "total", - "description": "Total number of records in the database", - "schema": { - "type": "number", - "description": "Total number of records in the database", - "example": 30 - }, - "required": true - }, { "in": "query", "name": "skip", - "description": "The number of skiped records for this query", + "description": "The number of records to skip for pagination", "schema": { - "type": "number", - "description": "The number of skiped records for this query", + "type": "string", + "default": "0", + "description": "The number of records to skip for pagination", "example": 0 - }, - "required": true + } }, { "in": "query", "name": "take", - "description": "The number of records returned for this query", + "description": "The number of records to return for pagination", "schema": { - "type": "number", - "description": "The number of records returned for this query", + "type": "string", + "default": "12", + "description": "The number of records to return for pagination", "example": 12 - }, - "required": true + } } ], "responses": { @@ -2980,38 +3660,27 @@ }, "required": true }, - { - "in": "query", - "name": "total", - "description": "Total number of records in the database", - "schema": { - "type": "number", - "description": "Total number of records in the database", - "example": 30 - }, - "required": true - }, { "in": "query", "name": "skip", - "description": "The number of skiped records for this query", + "description": "The number of records to skip for pagination", "schema": { - "type": "number", - "description": "The number of skiped records for this query", + "type": "string", + "default": "0", + "description": "The number of records to skip for pagination", "example": 0 - }, - "required": true + } }, { "in": "query", "name": "take", - "description": "The number of records returned for this query", + "description": "The number of records to return for pagination", "schema": { - "type": "number", - "description": "The number of records returned for this query", + "type": "string", + "default": "12", + "description": "The number of records to return for pagination", "example": 12 - }, - "required": true + } } ], "responses": { @@ -3196,38 +3865,27 @@ }, "required": true }, - { - "in": "query", - "name": "total", - "description": "Total number of records in the database", - "schema": { - "type": "number", - "description": "Total number of records in the database", - "example": 30 - }, - "required": true - }, { "in": "query", "name": "skip", - "description": "The number of skiped records for this query", + "description": "The number of records to skip for pagination", "schema": { - "type": "number", - "description": "The number of skiped records for this query", + "type": "string", + "default": "0", + "description": "The number of records to skip for pagination", "example": 0 - }, - "required": true + } }, { "in": "query", "name": "take", - "description": "The number of records returned for this query", + "description": "The number of records to return for pagination", "schema": { - "type": "number", - "description": "The number of records returned for this query", + "type": "string", + "default": "12", + "description": "The number of records to return for pagination", "example": 12 - }, - "required": true + } } ], "responses": { diff --git a/packages/openapi/src/apiResponseSchema/avs/avsResponse.ts b/packages/openapi/src/apiResponseSchema/avs/avsResponse.ts index 7c9259ba..7f517234 100644 --- a/packages/openapi/src/apiResponseSchema/avs/avsResponse.ts +++ b/packages/openapi/src/apiResponseSchema/avs/avsResponse.ts @@ -57,6 +57,10 @@ export const AvsSchema = z.object({ Eigen: 1000000, cbETH: 2000000, }, + tvlStrategiesEth: { + stETH: 1000000, + cbETH: 2000000, + }, }, }), }); diff --git a/packages/openapi/src/apiResponseSchema/base/strategyTvlResponse.ts b/packages/openapi/src/apiResponseSchema/base/strategyTvlResponse.ts index fbbc7adc..3b99b9aa 100644 --- a/packages/openapi/src/apiResponseSchema/base/strategyTvlResponse.ts +++ b/packages/openapi/src/apiResponseSchema/base/strategyTvlResponse.ts @@ -7,6 +7,13 @@ const StrategyTvl = z ) .openapi({ example: 1000000 }); +const StrategyEthTvl = z + .number() + .describe( + 'The total value locked (TVL) in the strategy, denominated in ETH' + ) + .openapi({ example: 1000000 }); + const StrategyName = z .string() .describe('The name of the strategy') @@ -23,3 +30,15 @@ export const StrategyTvlSchema = z stETH: 2000000, }, }); + +export const StrategyEthTvlSchema = z + .record(StrategyName, StrategyEthTvl) + .describe( + 'The total value locked (TVL) in each restaking strategy, denominated in ETH' + ) + .openapi({ + example: { + cbETH: 1000000, + stETH: 2000000, + }, + }); diff --git a/packages/openapi/src/apiResponseSchema/base/tvlResponses.ts b/packages/openapi/src/apiResponseSchema/base/tvlResponses.ts index 7df5396b..ebecac90 100644 --- a/packages/openapi/src/apiResponseSchema/base/tvlResponses.ts +++ b/packages/openapi/src/apiResponseSchema/base/tvlResponses.ts @@ -1,5 +1,5 @@ import z from '../../../../api/src/schema/zod'; -import { StrategyTvlSchema } from './strategyTvlResponse'; +import { StrategyTvlSchema, StrategyEthTvlSchema } from './strategyTvlResponse'; export const TvlSchema = z.object({ tvl: z @@ -21,4 +21,7 @@ export const TvlSchema = z.object({ tvlStrategies: StrategyTvlSchema.describe( 'The TVL of each individual restaking strategy in its native token' ).openapi({ example: { Eigen: 1000000, cbETH: 2000000 } }), + tvlStrategiesEth: StrategyEthTvlSchema.describe( + 'The TVL of each individual restaking strategy in ETH' + ).openapi({ example: { Eigen: 1000000, cbETH: 2000000 } }), }); diff --git a/packages/openapi/src/apiResponseSchema/metrics/summaryMetricsResponse.ts b/packages/openapi/src/apiResponseSchema/metrics/summaryMetricsResponse.ts index cccf81dd..ee396a1a 100644 --- a/packages/openapi/src/apiResponseSchema/metrics/summaryMetricsResponse.ts +++ b/packages/openapi/src/apiResponseSchema/metrics/summaryMetricsResponse.ts @@ -1,5 +1,8 @@ import z from '../../../../api/src/schema/zod'; -import { StrategyTvlSchema } from '../base/strategyTvlResponse'; +import { + StrategyEthTvlSchema, + StrategyTvlSchema, +} from '../base/strategyTvlResponse'; export const SummaryMetricsResponseSchema = z.object({ tvl: z @@ -15,6 +18,7 @@ export const SummaryMetricsResponseSchema = z.object({ ) .openapi({ example: 1000000 }), tvlStrategies: StrategyTvlSchema, + tvlStrategiesEth: StrategyEthTvlSchema, tvlBeaconChain: z .number() .describe( diff --git a/packages/openapi/src/apiResponseSchema/operatorResponse.ts b/packages/openapi/src/apiResponseSchema/operatorResponse.ts index c55a6b64..94b53f5d 100644 --- a/packages/openapi/src/apiResponseSchema/operatorResponse.ts +++ b/packages/openapi/src/apiResponseSchema/operatorResponse.ts @@ -48,6 +48,10 @@ export const OperatorResponseSchema = z.object({ Eigen: 1000000, cbETH: 2000000, }, + tvlStrategiesEth: { + stETH: 1000000, + cbETH: 2000000, + }, }, }), }); diff --git a/packages/openapi/src/apiResponseSchema/stakerResponse.ts b/packages/openapi/src/apiResponseSchema/stakerResponse.ts index fc222d65..1dbba91c 100644 --- a/packages/openapi/src/apiResponseSchema/stakerResponse.ts +++ b/packages/openapi/src/apiResponseSchema/stakerResponse.ts @@ -1,18 +1,6 @@ import z from '../../../api/src/schema/zod'; import { EthereumAddressSchema } from '../../../api/src/schema/zod/schemas/base/ethereumAddress'; - -// { -// "address": "0x0000006c21964af0d420af8992851a30fa13c68b", -// "operatorAddress": "0x71c6f7ed8c2d4925d0baf16f6a85bb1736d412eb", -// "shares": [ -// { -// "stakerAddress": "0x0000006c21964af0d420af8992851a30fa13c68b", -// "strategyAddress": "0x93c4b944d05dfe6df7645a86cd2206016c51564d", -// "shares": "40888428658906049" -// } -// ], -// "tvl": 0.040888428658906045 -// }, +import { TvlSchema } from './base/tvlResponses'; export const StakerSharesSchema = z.object({ stakerAddress: EthereumAddressSchema.describe( @@ -35,8 +23,22 @@ export const StakerResponseSchema = z.object({ 'The address of the operator' ).openapi({ example: '0x71c6f7ed8c2d4925d0baf16f6a85bb1736d412eb' }), shares: z.array(StakerSharesSchema), - tvl: z - .number() - .describe('The total value locked in the AVS staker') - .openapi({ example: 0.040888428658906045 }), + tvl: TvlSchema.optional() + .describe('The total value locked (TVL) in the AVS staker') + .openapi({ + example: { + tvl: 1000000, + tvlBeaconChain: 1000000, + tvlWETH: 1000000, + tvlRestaking: 1000000, + tvlStrategies: { + Eigen: 1000000, + cbETH: 2000000, + }, + tvlStrategiesEth: { + stETH: 1000000, + cbETH: 2000000, + }, + }, + }), }); diff --git a/packages/openapi/src/documentBase.ts b/packages/openapi/src/documentBase.ts index 35b92579..e5b32e00 100644 --- a/packages/openapi/src/documentBase.ts +++ b/packages/openapi/src/documentBase.ts @@ -1,5 +1,6 @@ import { openApiErrorResponses } from './apiResponseSchema/base/errorResponses'; import { createDocument } from 'zod-openapi'; +import { systemRoutes } from './routes/system'; import { avsRoutes } from './routes/avs'; import { metricsRoutes } from './routes/metrics'; import { operatorsRoutes } from './routes/operators'; @@ -25,6 +26,7 @@ export const document = createDocument({ }, ], paths: { + ...systemRoutes, ...metricsRoutes, ...avsRoutes, ...operatorsRoutes, diff --git a/packages/openapi/src/routes/avs/getAvsStakersByAddress.ts b/packages/openapi/src/routes/avs/getAvsStakersByAddress.ts index 077a4c91..ab8866a4 100644 --- a/packages/openapi/src/routes/avs/getAvsStakersByAddress.ts +++ b/packages/openapi/src/routes/avs/getAvsStakersByAddress.ts @@ -5,11 +5,17 @@ import { ZodOpenApiOperationObject } from 'zod-openapi'; import { PaginationQuerySchema } from '../../../../api/src/schema/zod/schemas/paginationQuery'; import { PaginationMetaResponsesSchema } from '../../apiResponseSchema/base/paginationMetaResponses'; import { StakerResponseSchema } from '../../apiResponseSchema/stakerResponse'; +import { WithTvlQuerySchema } from '../../../../api/src/schema/zod/schemas/withTvlQuery'; const EthereumAddressParam = z.object({ address: EthereumAddressSchema, }); +const CombinedQuerySchema = z + .object({}) + .merge(WithTvlQuerySchema) + .merge(PaginationQuerySchema); + const AvsStakerResponseSchema = z.object({ data: z.array(StakerResponseSchema), meta: PaginationMetaResponsesSchema, @@ -23,7 +29,7 @@ export const getAvsStakersByAddress: ZodOpenApiOperationObject = { tags: ['AVS'], requestParams: { path: EthereumAddressParam, - query: PaginationQuerySchema, + query: CombinedQuerySchema, }, responses: { '200': { diff --git a/packages/openapi/src/routes/metrics/getTvlRestaking.ts b/packages/openapi/src/routes/metrics/getTvlRestaking.ts index 2ccd30e7..807dc853 100644 --- a/packages/openapi/src/routes/metrics/getTvlRestaking.ts +++ b/packages/openapi/src/routes/metrics/getTvlRestaking.ts @@ -2,7 +2,10 @@ import { ZodOpenApiOperationObject } from 'zod-openapi'; import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; import { TvlResponseSchema } from '../../apiResponseSchema/metrics/tvlResponse'; import z from '../../../../api/src/schema/zod'; -import { StrategyTvlSchema } from '../../apiResponseSchema/base/strategyTvlResponse'; +import { + StrategyTvlSchema, + StrategyEthTvlSchema, +} from '../../apiResponseSchema/base/strategyTvlResponse'; const RestakingTvlResponseSchema = TvlResponseSchema.extend({ tvl: z @@ -10,6 +13,7 @@ const RestakingTvlResponseSchema = TvlResponseSchema.extend({ .describe('The value of the combined restaking strategy TVL in ETH') .openapi({ example: 1000000 }), tvlStrategies: StrategyTvlSchema, + tvlStrategiesEth: StrategyEthTvlSchema, }); export const getRestakingTvlMetrics: ZodOpenApiOperationObject = { diff --git a/packages/openapi/src/routes/operators/getAllOperators.ts b/packages/openapi/src/routes/operators/getAllOperators.ts index d831ec70..91587f1b 100644 --- a/packages/openapi/src/routes/operators/getAllOperators.ts +++ b/packages/openapi/src/routes/operators/getAllOperators.ts @@ -27,7 +27,7 @@ export const getAllOperators: ZodOpenApiOperationObject = { }, responses: { '200': { - description: 'The list of Operators records.', + description: 'The list of operator records.', content: { 'application/json': { schema: AllOperatorsResponseSchema, diff --git a/packages/openapi/src/routes/stakers/getAllStakers.ts b/packages/openapi/src/routes/stakers/getAllStakers.ts new file mode 100644 index 00000000..3004a3fd --- /dev/null +++ b/packages/openapi/src/routes/stakers/getAllStakers.ts @@ -0,0 +1,39 @@ +import { ZodOpenApiOperationObject } from 'zod-openapi'; +import z from '../../../../api/src/schema/zod'; +import { PaginationQuerySchema } from '../../../../api/src/schema/zod/schemas/paginationQuery'; +import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; +import { PaginationMetaResponsesSchema } from '../../apiResponseSchema/base/paginationMetaResponses'; +import { WithTvlQuerySchema } from '../../../../api/src/schema/zod/schemas/withTvlQuery'; +import { StakerResponseSchema } from '../../apiResponseSchema/stakerResponse'; + +const AllStakersResponseSchema = z.object({ + data: z.array(StakerResponseSchema), + meta: PaginationMetaResponsesSchema, +}); + +const CombinedQuerySchema = z + .object({}) + .merge(WithTvlQuerySchema) + .merge(PaginationQuerySchema); + +export const getAllStakers: ZodOpenApiOperationObject = { + operationId: 'getAllStakers', + summary: 'Retrieve all stakers', + description: + 'Returns all staker records. This endpoint supports pagination.', + tags: ['Stakers'], + requestParams: { + query: CombinedQuerySchema, + }, + responses: { + '200': { + description: 'The list of staker records.', + content: { + 'application/json': { + schema: AllStakersResponseSchema, + }, + }, + }, + ...openApiErrorResponses, + }, +}; diff --git a/packages/openapi/src/routes/stakers/getCompletedStakerWithdrawals.ts b/packages/openapi/src/routes/stakers/getCompletedStakerWithdrawals.ts index 670ce65d..ade58f9f 100644 --- a/packages/openapi/src/routes/stakers/getCompletedStakerWithdrawals.ts +++ b/packages/openapi/src/routes/stakers/getCompletedStakerWithdrawals.ts @@ -2,6 +2,7 @@ import z from '../../../../api/src/schema/zod'; import { ZodOpenApiOperationObject } from 'zod-openapi'; import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; import { PaginationMetaResponsesSchema } from '../../apiResponseSchema/base/paginationMetaResponses'; +import { PaginationQuerySchema } from '../../../../api/src/schema/zod/schemas/paginationQuery'; import { WithdrawalsResponseSchema } from '../../apiResponseSchema/withdrawals/withdrawalsResponseSchema'; import { EthereumAddressSchema } from '../../../../api/src/schema/zod/schemas/base/ethereumAddress'; @@ -24,7 +25,7 @@ export const getCompletedStakerWithdrawals: ZodOpenApiOperationObject = { tags: ['Stakers'], requestParams: { path: StakerAddressParam, - query: PaginationMetaResponsesSchema, + query: PaginationQuerySchema, }, responses: { '200': { diff --git a/packages/openapi/src/routes/stakers/getQueuedStakerWithdrawals.ts b/packages/openapi/src/routes/stakers/getQueuedStakerWithdrawals.ts index fd3c4684..4c012e19 100644 --- a/packages/openapi/src/routes/stakers/getQueuedStakerWithdrawals.ts +++ b/packages/openapi/src/routes/stakers/getQueuedStakerWithdrawals.ts @@ -1,6 +1,7 @@ import z from '../../../../api/src/schema/zod'; import { ZodOpenApiOperationObject } from 'zod-openapi'; import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; +import { PaginationQuerySchema } from '../../../../api/src/schema/zod/schemas/paginationQuery'; import { PaginationMetaResponsesSchema } from '../../apiResponseSchema/base/paginationMetaResponses'; import { WithdrawalsResponseSchema } from '../../apiResponseSchema/withdrawals/withdrawalsResponseSchema'; import { EthereumAddressSchema } from '../../../../api/src/schema/zod/schemas/base/ethereumAddress'; @@ -23,7 +24,7 @@ export const getQueuedStakerWithdrawals: ZodOpenApiOperationObject = { tags: ['Stakers'], requestParams: { path: StakerAddressParam, - query: PaginationMetaResponsesSchema, + query: PaginationQuerySchema, }, responses: { '200': { diff --git a/packages/openapi/src/routes/stakers/getQueuedWithdrawableStakerWithdrawals.ts b/packages/openapi/src/routes/stakers/getQueuedWithdrawableStakerWithdrawals.ts index a4744390..252c3c2c 100644 --- a/packages/openapi/src/routes/stakers/getQueuedWithdrawableStakerWithdrawals.ts +++ b/packages/openapi/src/routes/stakers/getQueuedWithdrawableStakerWithdrawals.ts @@ -1,6 +1,7 @@ import z from '../../../../api/src/schema/zod'; import { ZodOpenApiOperationObject } from 'zod-openapi'; import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; +import { PaginationQuerySchema } from '../../../../api/src/schema/zod/schemas/paginationQuery'; import { PaginationMetaResponsesSchema } from '../../apiResponseSchema/base/paginationMetaResponses'; import { WithdrawalsResponseSchema } from '../../apiResponseSchema/withdrawals/withdrawalsResponseSchema'; import { EthereumAddressSchema } from '../../../../api/src/schema/zod/schemas/base/ethereumAddress'; @@ -26,7 +27,7 @@ export const getQueuedWithdrawableStakerWithdrawals: ZodOpenApiOperationObject = tags: ['Stakers'], requestParams: { path: StakerAddressParam, - query: PaginationMetaResponsesSchema, + query: PaginationQuerySchema, }, responses: { '200': { diff --git a/packages/openapi/src/routes/stakers/getStakerByAddress.ts b/packages/openapi/src/routes/stakers/getStakerByAddress.ts new file mode 100644 index 00000000..c034f577 --- /dev/null +++ b/packages/openapi/src/routes/stakers/getStakerByAddress.ts @@ -0,0 +1,34 @@ +import { ZodOpenApiOperationObject } from 'zod-openapi'; +import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; +import z from '../../../../api/src/schema/zod'; +import { EthereumAddressSchema } from '../../../../api/src/schema/zod/schemas/base/ethereumAddress'; +import { WithTvlQuerySchema } from '../../../../api/src/schema/zod/schemas/withTvlQuery'; +import { StakerResponseSchema } from '../../apiResponseSchema/stakerResponse'; + +const StakerAddressParam = z.object({ + address: EthereumAddressSchema.describe( + 'The address of the staker' + ).openapi({ example: '0x00107cfdeaddc0a3160ed2f6fedd627f313e7b1b' }), +}); + +export const getStakerByAddress: ZodOpenApiOperationObject = { + operationId: 'getStakerByAddress', + summary: 'Retrieve a staker by address', + description: 'Returns a staker record by address.', + tags: ['Stakers'], + requestParams: { + query: WithTvlQuerySchema, + path: StakerAddressParam, + }, + responses: { + '200': { + description: 'The record of the requested operator.', + content: { + 'application/json': { + schema: StakerResponseSchema, + }, + }, + }, + ...openApiErrorResponses, + }, +}; diff --git a/packages/openapi/src/routes/stakers/getStakerWithdrawals.ts b/packages/openapi/src/routes/stakers/getStakerWithdrawals.ts index 2ac427cc..27cd142b 100644 --- a/packages/openapi/src/routes/stakers/getStakerWithdrawals.ts +++ b/packages/openapi/src/routes/stakers/getStakerWithdrawals.ts @@ -1,6 +1,7 @@ import z from '../../../../api/src/schema/zod'; import { ZodOpenApiOperationObject } from 'zod-openapi'; import { openApiErrorResponses } from '../../apiResponseSchema/base/errorResponses'; +import { PaginationQuerySchema } from '../../../../api/src/schema/zod/schemas/paginationQuery'; import { PaginationMetaResponsesSchema } from '../../apiResponseSchema/base/paginationMetaResponses'; import { WithdrawalsResponseSchema } from '../../apiResponseSchema/withdrawals/withdrawalsResponseSchema'; import { EthereumAddressSchema } from '../../../../api/src/schema/zod/schemas/base/ethereumAddress'; @@ -24,7 +25,7 @@ export const getStakerWithdrawals: ZodOpenApiOperationObject = { tags: ['Stakers'], requestParams: { path: StakerAddressParam, - query: PaginationMetaResponsesSchema, + query: PaginationQuerySchema, }, responses: { '200': { diff --git a/packages/openapi/src/routes/stakers/index.ts b/packages/openapi/src/routes/stakers/index.ts index e365878a..8162400a 100644 --- a/packages/openapi/src/routes/stakers/index.ts +++ b/packages/openapi/src/routes/stakers/index.ts @@ -1,10 +1,14 @@ import { ZodOpenApiPathsObject } from 'zod-openapi'; +import { getAllStakers } from './getAllStakers'; +import { getStakerByAddress } from './getStakerByAddress'; import { getStakerWithdrawals } from './getStakerWithdrawals'; import { getQueuedStakerWithdrawals } from './getQueuedStakerWithdrawals'; import { getQueuedWithdrawableStakerWithdrawals } from './getQueuedWithdrawableStakerWithdrawals'; import { getCompletedStakerWithdrawals } from './getCompletedStakerWithdrawals'; export const stakersRoutes: ZodOpenApiPathsObject = { + '/stakers': { get: getAllStakers }, + '/stakers/{address}': { get: getStakerByAddress }, '/stakers/{address}/withdrawals': { get: getStakerWithdrawals, }, diff --git a/packages/openapi/src/routes/system/getHealth.ts b/packages/openapi/src/routes/system/getHealth.ts new file mode 100644 index 00000000..f87f65ec --- /dev/null +++ b/packages/openapi/src/routes/system/getHealth.ts @@ -0,0 +1,27 @@ +import { ZodOpenApiOperationObject } from 'zod-openapi'; +import z from '../../../../api/src/schema/zod'; + +const HealthResponseSchema = z.object({ + status: z + .string() + .describe('The status of the API server') + .openapi({ example: 'ok' }), +}); + +export const getHealth: ZodOpenApiOperationObject = { + operationId: 'getHealth', + summary: 'Retrieve API server status', + description: 'Returns API server status.', + tags: ['System'], + requestParams: {}, + responses: { + '200': { + description: 'The API server status.', + content: { + 'application/json': { + schema: HealthResponseSchema, + }, + }, + }, + }, +}; diff --git a/packages/openapi/src/routes/system/getVersion.ts b/packages/openapi/src/routes/system/getVersion.ts new file mode 100644 index 00000000..79fc6a29 --- /dev/null +++ b/packages/openapi/src/routes/system/getVersion.ts @@ -0,0 +1,27 @@ +import { ZodOpenApiOperationObject } from 'zod-openapi'; +import z from '../../../../api/src/schema/zod'; + +const VersionResponseSchema = z.object({ + version: z + .string() + .describe('The version of the API server') + .openapi({ example: 'v0.0.1' }), +}); + +export const getVersion: ZodOpenApiOperationObject = { + operationId: 'getVersion', + summary: 'Retrieve API server version', + description: 'Returns API server version.', + tags: ['System'], + requestParams: {}, + responses: { + '200': { + description: 'The API server version.', + content: { + 'application/json': { + schema: VersionResponseSchema, + }, + }, + }, + }, +}; diff --git a/packages/openapi/src/routes/system/index.ts b/packages/openapi/src/routes/system/index.ts new file mode 100644 index 00000000..fbe39b1e --- /dev/null +++ b/packages/openapi/src/routes/system/index.ts @@ -0,0 +1,10 @@ +import { ZodOpenApiPathsObject } from 'zod-openapi'; +import { getHealth } from './getHealth'; +import { getVersion } from './getVersion'; + +export const systemRoutes: ZodOpenApiPathsObject = { + '/version': { get: getVersion }, + '/health': { + get: getHealth, + }, +}; From c1d88209fdef0456c43beb09357af6bd45765e45 Mon Sep 17 00:00:00 2001 From: Udit Date: Mon, 17 Jun 2024 20:16:40 +0530 Subject: [PATCH 62/62] Hot patch, remove next iterator count addition --- packages/seeder/src/utils/seeder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/seeder/src/utils/seeder.ts b/packages/seeder/src/utils/seeder.ts index b1e85074..b7fc4545 100644 --- a/packages/seeder/src/utils/seeder.ts +++ b/packages/seeder/src/utils/seeder.ts @@ -28,7 +28,7 @@ export async function loopThroughBlocks( await cb(currentBlock, nextBlock) - currentBlock = nextBlock + 1n + currentBlock = nextBlock } return lastBlock