diff --git a/rewards-squid/src/blocks/utils.ts b/rewards-squid/src/blocks/utils.ts index 469a96d74..670604c31 100644 --- a/rewards-squid/src/blocks/utils.ts +++ b/rewards-squid/src/blocks/utils.ts @@ -1,6 +1,7 @@ import { StoreWithCache } from "@belopash/typeorm-store"; import { ApiPromise, WsProvider } from "@polkadot/api"; import * as ss58 from "@subsquid/ss58"; +import { randomUUID } from "crypto"; import { Account, DomainEpoch, @@ -30,42 +31,46 @@ export function encodeId(id: Uint8Array | string) { * @param api * @returns */ -export async function createOperator( +export async function getOrCreateOperator( ctx: ProcessorContext, header: BlockHeader, - event: Event + operatorId: bigint ): Promise { - const { operatorId } = events.domains.operatorRegistered.v0.decode(event); let operator = await ctx.store.get(Operator, operatorId.toString()); - const operatorInfo = await domains.operators.v1.get(header, operatorId); - const nominatorsLength = await domains.nominatorCount.v0.get( - header, - operatorId - ); - - const ownerAccount = await domains.operatorIdOwner.v0.get(header, operatorId); - const encodedOwnerAccount = encodeId(ownerAccount || ""); - - if (!operator && operatorInfo) { - operator = new Operator({ - id: operatorId.toString(), - orderingId: Number(operatorId), - operatorOwner: encodedOwnerAccount, - status: JSON.stringify(operatorInfo.status), - signingKey: operatorInfo.signingKey, - totalShares: operatorInfo.currentTotalShares, - currentEpochRewards: operatorInfo.currentEpochRewards, - currentTotalStake: operatorInfo.currentTotalStake, - nominatorAmount: nominatorsLength, - nominationTax: operatorInfo.nominationTax, - minimumNominatorStake: operatorInfo.minimumNominatorStake, - nextDomainId: operatorInfo.nextDomainId, - currentDomainId: operatorInfo.currentDomainId, - updatedAt: header.height, - }); + if (!operator) { + const operatorInfo = await domains.operators.v1.get(header, operatorId); + const nominatorsLength = await domains.nominatorCount.v0.get( + header, + operatorId + ); - await ctx.store.insert(operator); + const ownerAccount = await domains.operatorIdOwner.v0.get( + header, + operatorId + ); + const encodedOwnerAccount = encodeId(ownerAccount || ""); + + if (operatorInfo) { + operator = new Operator({ + id: operatorId.toString(), + orderingId: Number(operatorId), + operatorOwner: encodedOwnerAccount, + status: JSON.stringify(operatorInfo.status), + signingKey: operatorInfo.signingKey, + totalShares: operatorInfo.currentTotalShares, + currentEpochRewards: operatorInfo.currentEpochRewards, + currentTotalStake: operatorInfo.currentTotalStake, + nominatorAmount: nominatorsLength || 0, + nominationTax: operatorInfo.nominationTax, + minimumNominatorStake: operatorInfo.minimumNominatorStake, + nextDomainId: operatorInfo.nextDomainId, + currentDomainId: operatorInfo.currentDomainId, + updatedAt: header.height, + }); + + await ctx.store.insert(operator); + } } return operator; @@ -79,7 +84,8 @@ export async function getOrCreateNominator( ): Promise { const operatorIdStr = operatorId.toString(); const encodedNominatorId = encodeId(nominatorId); - let operator = await ctx.store.get(Operator, operatorIdStr); + const operator = await getOrCreateOperator(ctx, header, operatorId); + let nominator = await ctx.store.get( Nominator, `${operatorIdStr}-${encodedNominatorId}` @@ -95,7 +101,7 @@ export async function getOrCreateNominator( const account = await getOrCreateAccount(ctx, nominatorId); nominator = new Nominator({ - id: `${operatorIdStr}-${nominatorId}`, + id: `${operatorIdStr}-${encodedNominatorId}`, operator: operator, account: account, shares: BigInt(nominatorInfo?.known.shares || 0), @@ -108,54 +114,6 @@ export async function getOrCreateNominator( return nominator; } -export async function getOrCreateNominators( - ctx: ProcessorContext, - header: BlockHeader, - operator: Operator -): Promise { - const provider = new WsProvider(process.env.RPC_ENDPOINT); - const api = await ApiPromise.create({ provider, types: TYPES }); - - const nominatorsList: Nominator[] = []; - const operatorId = BigInt(operator.id); - const blockHeight = header.height; - - const nominators = await api.query.domains.deposits.entries(operatorId); - const nominatorsLength = nominators.length; - - for (let i = 0; i < nominatorsLength; i++) { - const nominatorId = nominators[i][0].args[1].toString(); - - let nominator = await ctx.store.get( - Nominator, - `${operator.id}-${nominatorId}` - ); - - const nominatorInfo = nominators[i][1].toJSON() as any; - - const existingNominator = await ctx.store.get(Nominator, nominatorId); - const hexAccountId = api.registry - .createType("AccountId", nominatorId) - .toHex(); - const account = await getOrCreateAccount(ctx, hexAccountId); - - nominator = new Nominator({ - ...existingNominator, - id: `${operator.id}-${nominatorId}`, - operator: operator, - account: account, - shares: BigInt(nominatorInfo.known.shares), - updatedAt: blockHeight, - }); - - await ctx.store.save(nominator); - - nominatorsList.push(nominator); - } - - return nominatorsList; -} - export async function getOrCreateAccount( ctx: ProcessorContext, accountId: string @@ -254,22 +212,18 @@ export async function updateOperatorRewards( return operatorEvents; } -export async function updateEpochCompleted( - ctx: ProcessorContext, - header: BlockHeader, - event: Event -) { +export async function updateEpochCompleted(header: BlockHeader, event: Event) { const { domainId, completedEpochIndex } = events.domains.domainEpochCompleted.v0.decode(event); const domainEpoch = new DomainEpoch({ - id: `${domainId}-${completedEpochIndex}-${header.height}`, + id: randomUUID(), domainId: domainId, epoch: completedEpochIndex, updatedAt: header.height, }); - ctx.store.save(domainEpoch); + return domainEpoch; } export async function updateOperatorStake( diff --git a/rewards-squid/src/main.ts b/rewards-squid/src/main.ts index 50110b384..0aee08424 100644 --- a/rewards-squid/src/main.ts +++ b/rewards-squid/src/main.ts @@ -3,7 +3,7 @@ import { TypeormDatabaseWithCache, } from "@belopash/typeorm-store"; import { - createOperator, + getOrCreateOperator, processRewardEvent, updateEpochCompleted, updateOperatorRewards, @@ -11,7 +11,7 @@ import { updateOperatorStatus, updateWithdrewStake, } from "./blocks/utils"; -import { OperatorRewardEvent, RewardEvent } from "./model"; +import { DomainEpoch, OperatorRewardEvent, RewardEvent } from "./model"; import { ProcessorContext, processor } from "./processor"; import { events } from "./types"; @@ -22,12 +22,14 @@ processor.run( await ctx.store.save([...rewards.operatorEvents]); await ctx.store.save([...rewards.rewardEvents]); + await ctx.store.save([...rewards.domainEpochEvents]); } ); type Rewards = { rewardEvents: RewardEvent[]; operatorEvents: OperatorRewardEvent[]; + domainEpochEvents: DomainEpoch[]; }; async function getOperatorEvents( @@ -35,14 +37,21 @@ async function getOperatorEvents( ): Promise { const rewardEvents: RewardEvent[] = []; const operatorEvents: OperatorRewardEvent[] = []; + const domainEpochEvents: DomainEpoch[] = []; for (let block of ctx.blocks) { for (let event of block.events) { switch (event.name) { case events.domains.domainEpochCompleted.name: - await updateEpochCompleted(ctx, block.header, event); + const domainEpochEvent = await updateEpochCompleted( + block.header, + event + ); + domainEpochEvents.push(domainEpochEvent); + break; case events.domains.operatorRegistered.name: - await createOperator(ctx, block.header, event); + const rec = events.domains.operatorRegistered.v0.decode(event); + await getOrCreateOperator(ctx, block.header, rec.operatorId); break; case events.domains.operatorDeregistered.name: const operatorDeregistered = @@ -91,5 +100,5 @@ async function getOperatorEvents( } } - return { rewardEvents, operatorEvents }; + return { rewardEvents, operatorEvents, domainEpochEvents }; }