Skip to content

Commit

Permalink
Merge pull request #36 from Eigen-Explorer/feature/switch-operator-sh…
Browse files Browse the repository at this point in the history
…ares-to-stakers

Reinclude operator shares, seed with impacted staker data
  • Loading branch information
uditdc authored Apr 30, 2024
2 parents 617e194 + e9a425b commit ccf2a20
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 72 deletions.
1 change: 0 additions & 1 deletion packages/api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
EigenExplorerApiError,
handleAndReturnErrorResponse,
} from './schema/errors';
import { error } from 'console';

const PORT = process.env.PORT ? Number.parseInt(process.env.PORT) : 3002;

Expand Down
2 changes: 2 additions & 0 deletions packages/seeder/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { seedPods } from './seedPods'
import { seedValidatorsRestake } from './seedValidatorsRestake'
import { seedStakers } from './seedStakers'
import { getViemClient } from './utils/viemClient'
import { seedOperatorShares } from './seedOperatorShares'

console.log('Initializing seeder ...')

Expand All @@ -25,6 +26,7 @@ async function seedAvsLoop() {
await seedOperators(targetBlock)
await seedAvsOperators(targetBlock)
await seedStakers(targetBlock)
await seedOperatorShares(targetBlock)

await delay(120) // Wait for 2 minutes (120 seconds)
}
Expand Down
191 changes: 148 additions & 43 deletions packages/seeder/src/seedOperatorShares.ts
Original file line number Diff line number Diff line change
@@ -1,78 +1,183 @@
import { parseAbiItem } from 'viem'
import { getEigenContracts } from './data/address'
import { getViemClient } from './utils/viemClient'
import { getPrismaClient } from './utils/prismaClient'
import { bulkUpdateDbTransactions, IMap } from './utils/seeder'
import {
baseBlock,
bulkUpdateDbTransactions,
fetchLastSyncBlock,
IMap,
loopThroughBlocks,
saveLastSyncBlock
} from './utils/seeder'

export async function seedOperatorShares(operatorAddresses: string[]) {
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,
{ shares: bigint; strategyAddress: string }[]
> = new Map()

let currentIndex = 0
let nextIndex = 0
const totalOperators = await prismaClient.operator.count({
where: { address: { in: operatorAddresses } }
})
const firstBlock = fromBlock
? fromBlock
: await fetchLastSyncBlock(blockSyncKey)
const lastBlock = toBlock ? toBlock : await viemClient.getBlockNumber()

// biome-ignore lint/suspicious/noExplicitAny: <explanation>
const dbTransactions: any[] = []
if (firstBlock === baseBlock) {
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
})

while (nextIndex < totalOperators) {
nextIndex = currentIndex + 12
// Operators list
const operatorAddresses = logs.map((l) =>
String(l.args.operator).toLowerCase()
)

const operators = await prismaClient.operator.findMany({
const operatorInit = await prismaClient.operator.findMany({
where: { address: { in: operatorAddresses } },
skip: currentIndex,
take: 12,
include: {
stakers: {
include: {
shares: true
}
}
shares: true
}
})

operators.map((operator) => {
const sharesMap: IMap<string, string> = new Map()
for (const l in logs) {
const log = logs[l]

const operatorAddress = String(log.args.operator).toLowerCase()
const strategyAddress = String(log.args.strategy).toLowerCase()
const shares = log.args.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, [])
}
}

let foundSharesIndex = operatorShares
.get(operatorAddress)
.findIndex(
(os) =>
os.strategyAddress.toLowerCase() === strategyAddress.toLowerCase()
)

operator.stakers.map((staker) => {
staker.shares.map((s) => {
if (!sharesMap.has(s.strategyAddress)) {
sharesMap.set(s.strategyAddress, '0')
}
if (foundSharesIndex !== undefined && foundSharesIndex === -1) {
operatorShares
.get(operatorAddress)
.push({ shares: 0n, strategyAddress: strategyAddress })

sharesMap.set(
s.strategyAddress,
(
BigInt(sharesMap.get(s.strategyAddress)) + BigInt(s.shares)
).toString()
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
}
}

console.log(
`Operator shares updated between blocks ${fromBlock} ${toBlock}: ${logs.length}`
)
})

// biome-ignore lint/suspicious/noExplicitAny: <explanation>
const dbTransactions: any[] = []

if (firstBlock === baseBlock) {
// Clear existing table
dbTransactions.push(prismaClient.operatorStrategyShares.deleteMany())

const newOperatorShares: {
operatorAddress: string
strategyAddress: string
shares: string
}[] = []

for (const [operatorAddress, shares] of operatorShares) {
shares.map((share) => {
newOperatorShares.push({
operatorAddress,
strategyAddress: share.strategyAddress,
shares: share.shares.toString()
})
})
}

for (const [strategyAddress, shares] of sharesMap) {
dbTransactions.push(
prismaClient.operatorStrategyShares.createMany({
data: newOperatorShares,
skipDuplicates: true
})
)
} else {
for (const [operatorAddress, shares] of operatorShares) {
shares.map((share) => {
dbTransactions.push(
prismaClient.operatorStrategyShares.upsert({
where: {
operatorAddress_strategyAddress: {
operatorAddress: operator.address,
strategyAddress
operatorAddress,
strategyAddress: share.strategyAddress
}
},
create: {
operatorAddress: operator.address,
strategyAddress,
shares: shares.toString()
operatorAddress,
strategyAddress: share.strategyAddress,
shares: share.shares.toString()
},
update: {
shares: shares.toString()
shares: share.shares.toString()
}
})
)
}
})

currentIndex = nextIndex
})
}
}

await bulkUpdateDbTransactions(dbTransactions)

console.log('Seeded operator shares: ', totalOperators)
// Storing last sycned block
await saveLastSyncBlock(blockSyncKey, lastBlock)

console.log('Seeded operator shares:', operatorShares.size)
}
Loading

0 comments on commit ccf2a20

Please sign in to comment.