mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-04-22 02:07:55 +00:00
fix: compute staking score from CachedStakingDetails instead of hardcoded 0
This commit is contained in:
+63
-24
@@ -25,7 +25,8 @@ export interface UserScores {
|
||||
|
||||
export interface StakingScoreStatus {
|
||||
isTracking: boolean;
|
||||
hasCachedData: boolean; // Whether noter has submitted staking data
|
||||
hasCachedData: boolean;
|
||||
score: number; // 0-100 computed from CachedStakingDetails + duration
|
||||
startBlock: number | null;
|
||||
currentBlock: number;
|
||||
durationBlocks: number;
|
||||
@@ -177,58 +178,95 @@ export async function getReferralCount(
|
||||
// ========================================
|
||||
|
||||
/**
|
||||
* Check staking score tracking status
|
||||
* Storage: stakingScore.stakingStartBlock(address)
|
||||
* Check staking score tracking status and compute actual staking score.
|
||||
* Queries CachedStakingDetails from People Chain and calculates score
|
||||
* using the same formula as pallet_staking_score::get_staking_score().
|
||||
*
|
||||
* The stakingScore pallet is on People Chain. It receives staking data
|
||||
* from Asset Hub via XCM (stored in cachedStakingDetails).
|
||||
* Score Formula:
|
||||
* 1. Amount Score (20-50 points based on staked HEZ)
|
||||
* - 0-100 HEZ: 20, 101-250: 30, 251-750: 40, 751+: 50
|
||||
* 2. Duration Multiplier (time since startScoreTracking)
|
||||
* - <1mo: x1.0, 1-2mo: x1.2, 3-5mo: x1.4, 6-11mo: x1.7, 12+mo: x2.0
|
||||
* 3. Final = min(100, floor(amountScore * durationMultiplier))
|
||||
*/
|
||||
export async function getStakingScoreStatus(
|
||||
peopleApi: ApiPromise,
|
||||
address: string
|
||||
): Promise<StakingScoreStatus> {
|
||||
const empty: StakingScoreStatus = {
|
||||
isTracking: false, hasCachedData: false, score: 0,
|
||||
startBlock: null, currentBlock: 0, durationBlocks: 0,
|
||||
};
|
||||
|
||||
try {
|
||||
if (!peopleApi?.query?.stakingScore?.stakingStartBlock) {
|
||||
return { isTracking: false, hasCachedData: false, startBlock: null, currentBlock: 0, durationBlocks: 0 };
|
||||
return empty;
|
||||
}
|
||||
|
||||
const startBlockResult = await peopleApi.query.stakingScore.stakingStartBlock(address);
|
||||
const currentBlock = Number((await peopleApi.query.system.number()).toString());
|
||||
|
||||
if (startBlockResult.isEmpty || startBlockResult.isNone) {
|
||||
return { isTracking: false, hasCachedData: false, startBlock: null, currentBlock, durationBlocks: 0 };
|
||||
return { ...empty, currentBlock };
|
||||
}
|
||||
|
||||
const startBlock = Number(startBlockResult.toString());
|
||||
const durationBlocks = currentBlock - startBlock;
|
||||
|
||||
// Check if noter has submitted cached staking data
|
||||
// Query CachedStakingDetails for both sources
|
||||
let hasCachedData = false;
|
||||
let totalStakeWei = BigInt(0);
|
||||
if (peopleApi.query.stakingScore.cachedStakingDetails) {
|
||||
try {
|
||||
const [relayResult, assetHubResult] = await Promise.all([
|
||||
peopleApi.query.stakingScore.cachedStakingDetails(address, 'RelayChain')
|
||||
.catch(() => ({ isSome: false, isEmpty: true })),
|
||||
.catch(() => null),
|
||||
peopleApi.query.stakingScore.cachedStakingDetails(address, 'AssetHub')
|
||||
.catch(() => ({ isSome: false, isEmpty: true })),
|
||||
.catch(() => null),
|
||||
]);
|
||||
hasCachedData = (relayResult.isSome || !relayResult.isEmpty) ||
|
||||
(assetHubResult.isSome || !assetHubResult.isEmpty);
|
||||
if (relayResult && !relayResult.isEmpty && relayResult.isSome) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const json = (relayResult.unwrap() as any).toJSON();
|
||||
totalStakeWei += BigInt(json.stakedAmount ?? json.staked_amount ?? '0');
|
||||
hasCachedData = true;
|
||||
}
|
||||
if (assetHubResult && !assetHubResult.isEmpty && assetHubResult.isSome) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const json = (assetHubResult.unwrap() as any).toJSON();
|
||||
totalStakeWei += BigInt(json.stakedAmount ?? json.staked_amount ?? '0');
|
||||
hasCachedData = true;
|
||||
}
|
||||
} catch {
|
||||
hasCachedData = false;
|
||||
// keep defaults
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isTracking: true,
|
||||
hasCachedData,
|
||||
startBlock,
|
||||
currentBlock,
|
||||
durationBlocks
|
||||
};
|
||||
// Calculate staking score from cached data
|
||||
let score = 0;
|
||||
if (hasCachedData && totalStakeWei > BigInt(0)) {
|
||||
const stakedHEZ = Number(totalStakeWei / BigInt(10 ** 12));
|
||||
|
||||
// Amount tier
|
||||
let amountScore = 20;
|
||||
if (stakedHEZ > 750) amountScore = 50;
|
||||
else if (stakedHEZ > 250) amountScore = 40;
|
||||
else if (stakedHEZ > 100) amountScore = 30;
|
||||
|
||||
// Duration multiplier
|
||||
const MONTH = 432000; // ~30 days in blocks (6s per block)
|
||||
let mult = 1.0;
|
||||
if (durationBlocks >= 12 * MONTH) mult = 2.0;
|
||||
else if (durationBlocks >= 6 * MONTH) mult = 1.7;
|
||||
else if (durationBlocks >= 3 * MONTH) mult = 1.4;
|
||||
else if (durationBlocks >= MONTH) mult = 1.2;
|
||||
|
||||
score = Math.min(100, Math.floor(amountScore * mult));
|
||||
}
|
||||
|
||||
return { isTracking: true, hasCachedData, score, startBlock, currentBlock, durationBlocks };
|
||||
} catch (error) {
|
||||
console.error('Error fetching staking score status:', error);
|
||||
return { isTracking: false, hasCachedData: false, startBlock: null, currentBlock: 0, durationBlocks: 0 };
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,18 +350,19 @@ export async function getAllScores(
|
||||
}
|
||||
|
||||
try {
|
||||
const [trustScore, referralScore, tikiScore] = await Promise.all([
|
||||
const [trustScore, referralScore, tikiScore, stakingStatus] = await Promise.all([
|
||||
getTrustScore(peopleApi, address),
|
||||
getReferralScore(peopleApi, address),
|
||||
getTikiScore(peopleApi, address),
|
||||
getStakingScoreStatus(peopleApi, address),
|
||||
]);
|
||||
|
||||
return {
|
||||
trustScore,
|
||||
referralScore,
|
||||
stakingScore: 0, // Trust pallet already includes staking
|
||||
stakingScore: stakingStatus.score,
|
||||
tikiScore,
|
||||
totalScore: trustScore, // Trust score = composite score (on-chain calculated)
|
||||
totalScore: trustScore,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error fetching scores:', error);
|
||||
|
||||
Reference in New Issue
Block a user