From 7b58fa0e4adc621e44014665e72a5122995437ec Mon Sep 17 00:00:00 2001 From: Kurdistan Tech Ministry Date: Wed, 18 Feb 2026 04:07:45 +0300 Subject: [PATCH] feat: add AH GraphQL engine + block handler for pool stakers init - Add handleBlock to query live chain state for existing pool members - Add second GraphQL engine container for Asset Hub schema (port 3001) - Register block handler in pezkuwi-assethub.yaml --- docker-compose.prod.yml | 20 +++++++++++++++++- pezkuwi-assethub.yaml | 3 +++ src/mappings/PoolStakers.ts | 42 ++++++++++++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 0530e34..5fc111c 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -70,7 +70,6 @@ services: - 3000:3000 depends_on: - subquery-node-relay - - subquery-node-assethub restart: always environment: DB_USER: postgres @@ -83,6 +82,25 @@ services: - --playground - --indexer=http://subquery-node-relay:3000 + graphql-engine-assethub: + container_name: query-pezkuwi-ah + image: onfinality/subql-query:v1.5.0 + ports: + - 3001:3000 + depends_on: + - subquery-node-assethub + restart: always + environment: + DB_USER: postgres + DB_PASS: pezkuwi_subquery_2024 + DB_DATABASE: postgres + DB_HOST: postgres + DB_PORT: 5432 + command: + - --name=subquery-pezkuwi-assethub + - --playground + - --indexer=http://subquery-node-assethub:3000 + noter-bot: container_name: noter-pezkuwi build: diff --git a/pezkuwi-assethub.yaml b/pezkuwi-assethub.yaml index 94c251d..1563ebb 100644 --- a/pezkuwi-assethub.yaml +++ b/pezkuwi-assethub.yaml @@ -23,6 +23,9 @@ dataSources: mapping: file: ./dist/index.js handlers: + # Block handler: initialize active pool stakers from chain state + - handler: handleBlock + kind: substrate/BlockHandler # Signed extrinsics for history - handler: handleHistoryElement kind: substrate/CallHandler diff --git a/src/mappings/PoolStakers.ts b/src/mappings/PoolStakers.ts index c22e39c..78f13d2 100644 --- a/src/mappings/PoolStakers.ts +++ b/src/mappings/PoolStakers.ts @@ -1,4 +1,4 @@ -import { SubstrateEvent } from "@subql/types"; +import { SubstrateEvent, SubstrateBlock } from "@subql/types"; import { ActiveStaker } from "../types"; import { Option } from "@pezkuwi/types"; import { @@ -6,6 +6,46 @@ import { STAKING_TYPE_NOMINATION_POOL, } from "./constants"; +let poolMembersInitialized = false; + +/** + * Block handler: on the FIRST block processed, query the live chain state + * for all current nomination pool members and save them as ActiveStakers. + * This ensures existing pool members are captured even if their Bonded + * events were in pruned blocks. + */ +export async function handleBlock(block: SubstrateBlock): Promise { + if (poolMembersInitialized) return; + poolMembersInitialized = true; + + logger.info("Initializing active pool stakers from live chain state..."); + + const members = await api.query.nominationPools.poolMembers.entries(); + let count = 0; + + for (const [key, memberOpt] of members) { + const member = (memberOpt as Option); + if (member.isNone) continue; + + const unwrapped = member.unwrap(); + if (unwrapped.points.toBigInt() === BigInt(0)) continue; + + const address = key.args[0].toString(); + const stakerId = `${PEZKUWI_ASSET_HUB_GENESIS}-${STAKING_TYPE_NOMINATION_POOL}-${address}`; + + const staker = ActiveStaker.create({ + id: stakerId, + networkId: PEZKUWI_ASSET_HUB_GENESIS, + stakingType: STAKING_TYPE_NOMINATION_POOL, + address, + }); + await staker.save(); + count++; + } + + logger.info(`Initialized ${count} active pool stakers from chain state`); +} + /** * Handle nominationPools.Bonded event * Fired when a member bonds (joins or adds more) to a nomination pool.