mirror of
https://github.com/pezkuwichain/pezkuwi-subquery.git
synced 2026-04-22 01:57:58 +00:00
242 lines
5.7 KiB
TypeScript
242 lines
5.7 KiB
TypeScript
import {
|
|
AccountPoolReward,
|
|
AccumulatedReward,
|
|
AccumulatedPoolReward,
|
|
HistoryElement,
|
|
RewardType,
|
|
} from "../types";
|
|
import { SubstrateEvent } from "@subql/types";
|
|
import {
|
|
eventIdFromBlockAndIdxAndAddress,
|
|
timestamp,
|
|
eventIdWithAddress,
|
|
blockNumber,
|
|
} from "./common";
|
|
import {
|
|
handleGenericForTxHistory,
|
|
updateAccumulatedGenericReward,
|
|
} from "./Rewards";
|
|
import { getPoolMembers } from "./Cache";
|
|
import { Option } from "@pezkuwi/types";
|
|
|
|
export async function handlePoolReward(
|
|
rewardEvent: SubstrateEvent,
|
|
): Promise<void> {
|
|
await handlePoolRewardForTxHistory(rewardEvent);
|
|
let accumulatedReward = await updateAccumulatedPoolReward(rewardEvent, true);
|
|
let {
|
|
event: {
|
|
data: [accountId, poolId, amount],
|
|
},
|
|
} = rewardEvent;
|
|
await updateAccountPoolRewards(
|
|
rewardEvent,
|
|
accountId.toString(),
|
|
(amount as any).toBigInt(),
|
|
(poolId as any).toNumber(),
|
|
RewardType.reward,
|
|
accumulatedReward.amount,
|
|
);
|
|
}
|
|
|
|
async function handlePoolRewardForTxHistory(
|
|
rewardEvent: SubstrateEvent,
|
|
): Promise<void> {
|
|
const {
|
|
event: {
|
|
data: [account, poolId, amount],
|
|
},
|
|
} = rewardEvent;
|
|
handleGenericForTxHistory(
|
|
rewardEvent,
|
|
account.toString(),
|
|
async (element: HistoryElement) => {
|
|
element.poolReward = {
|
|
eventIdx: rewardEvent.idx,
|
|
amount: amount.toString(),
|
|
isReward: true,
|
|
poolId: (poolId as any).toNumber(),
|
|
};
|
|
return element;
|
|
},
|
|
);
|
|
}
|
|
|
|
async function updateAccumulatedPoolReward(
|
|
event: SubstrateEvent,
|
|
isReward: boolean,
|
|
): Promise<AccumulatedReward> {
|
|
let {
|
|
event: {
|
|
data: [accountId, _, amount],
|
|
},
|
|
} = event;
|
|
return await updateAccumulatedGenericReward(
|
|
AccumulatedPoolReward,
|
|
accountId.toString(),
|
|
(amount as any).toBigInt(),
|
|
isReward,
|
|
);
|
|
}
|
|
|
|
async function updateAccountPoolRewards(
|
|
event: SubstrateEvent,
|
|
accountAddress: string,
|
|
amount: bigint,
|
|
poolId: number,
|
|
rewardType: RewardType,
|
|
accumulatedAmount: bigint,
|
|
): Promise<void> {
|
|
let id = eventIdWithAddress(event, accountAddress);
|
|
let accountPoolReward = new AccountPoolReward(
|
|
id,
|
|
accountAddress,
|
|
blockNumber(event),
|
|
timestamp(event.block),
|
|
amount,
|
|
accumulatedAmount,
|
|
rewardType,
|
|
poolId,
|
|
);
|
|
await accountPoolReward.save();
|
|
}
|
|
|
|
export async function handlePoolBondedSlash(
|
|
bondedSlashEvent: SubstrateEvent,
|
|
): Promise<void> {
|
|
const {
|
|
event: {
|
|
data: [poolIdEncoded, slash],
|
|
},
|
|
} = bondedSlashEvent;
|
|
const poolId = (poolIdEncoded as any).toNumber();
|
|
|
|
const poolOption = (await api.query.nominationPools.bondedPools(
|
|
poolId,
|
|
)) as Option<any>;
|
|
const pool = poolOption.unwrap();
|
|
|
|
await handleRelaychainPooledStakingSlash(
|
|
bondedSlashEvent,
|
|
poolId,
|
|
pool.points.toBigInt(),
|
|
(slash as any).toBigInt(),
|
|
(member: any): bigint => {
|
|
return member.points.toBigInt();
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function handlePoolUnbondingSlash(
|
|
unbondingSlashEvent: SubstrateEvent,
|
|
): Promise<void> {
|
|
const {
|
|
event: {
|
|
data: [poolId, era, slash],
|
|
},
|
|
} = unbondingSlashEvent;
|
|
const poolIdNumber = (poolId as any).toNumber();
|
|
const eraIdNumber = (era as any).toNumber();
|
|
|
|
const unbondingPools = (
|
|
(await api.query.nominationPools.subPoolsStorage(
|
|
poolIdNumber,
|
|
)) as Option<any>
|
|
).unwrap();
|
|
|
|
const pool =
|
|
(unbondingPools.withEra as any).get(eraIdNumber) ?? unbondingPools.noEra;
|
|
|
|
await handleRelaychainPooledStakingSlash(
|
|
unbondingSlashEvent,
|
|
poolIdNumber,
|
|
pool.points.toBigInt(),
|
|
(slash as any).toBigInt(),
|
|
(member: any): bigint => {
|
|
return (
|
|
(member.unbondingEras as any).get(eraIdNumber)?.toBigInt() ?? BigInt(0)
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
async function handleRelaychainPooledStakingSlash(
|
|
event: SubstrateEvent,
|
|
poolId: number,
|
|
poolPoints: bigint,
|
|
slash: bigint,
|
|
memberPointsCounter: (member: any) => bigint,
|
|
): Promise<void> {
|
|
if (poolPoints == BigInt(0)) {
|
|
return;
|
|
}
|
|
|
|
const members = await getPoolMembers(blockNumber(event));
|
|
|
|
for (const [accountId, member] of members) {
|
|
let memberPoints: bigint;
|
|
if (member.poolId.toNumber() === poolId) {
|
|
memberPoints = memberPointsCounter(member);
|
|
if (memberPoints != BigInt(0)) {
|
|
const personalSlash = (slash * memberPoints) / poolPoints;
|
|
|
|
await handlePoolSlashForTxHistory(
|
|
event,
|
|
poolId,
|
|
accountId,
|
|
personalSlash,
|
|
);
|
|
let accumulatedReward = await updateAccumulatedGenericReward(
|
|
AccumulatedPoolReward,
|
|
accountId,
|
|
personalSlash,
|
|
false,
|
|
);
|
|
await updateAccountPoolRewards(
|
|
event,
|
|
accountId,
|
|
personalSlash,
|
|
poolId,
|
|
RewardType.slash,
|
|
accumulatedReward.amount,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async function handlePoolSlashForTxHistory(
|
|
slashEvent: SubstrateEvent,
|
|
poolId: number,
|
|
accountId: string,
|
|
personalSlash: bigint,
|
|
): Promise<void> {
|
|
const extrinsic = slashEvent.extrinsic;
|
|
const block = slashEvent.block;
|
|
const blockNum = block.block.header.number.toString();
|
|
const blockTimestamp = timestamp(block);
|
|
const evtId = eventIdFromBlockAndIdxAndAddress(
|
|
blockNum,
|
|
slashEvent.idx.toString(),
|
|
accountId,
|
|
);
|
|
|
|
const element = HistoryElement.create({
|
|
id: evtId,
|
|
timestamp: blockTimestamp,
|
|
blockNumber: block.block.header.number.toNumber(),
|
|
extrinsicHash:
|
|
extrinsic !== undefined ? extrinsic.extrinsic.hash.toString() : null,
|
|
extrinsicIdx: extrinsic !== undefined ? extrinsic.idx : null,
|
|
address: accountId,
|
|
poolReward: {
|
|
eventIdx: slashEvent.idx,
|
|
amount: personalSlash.toString(),
|
|
isReward: false,
|
|
poolId: poolId,
|
|
},
|
|
});
|
|
|
|
await element.save();
|
|
}
|