feat: 3-state staking score UI with cached data support

This commit is contained in:
2026-02-17 01:56:49 +03:00
parent 0f63c96b2c
commit 9b97c63a26
12 changed files with 71 additions and 13 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "pezkuwi-telegram-miniapp",
"version": "1.0.202",
"version": "1.0.205",
"type": "module",
"description": "Pezkuwichain Telegram Mini App - Forum, Announcements, Rewards",
"author": "Pezkuwichain Team",
+1
View File
@@ -110,6 +110,7 @@ const ar: Translations = {
citizen: 'مواطن',
staking: 'التخزين',
stakingNotStarted: 'لم يبدأ بعد',
stakingWaitingData: 'في انتظار البيانات...',
stakingCountedInTrust: 'يُحتسب في نقاط الثقة',
people: '{count} شخص',
tiki: 'تيكي',
+1
View File
@@ -111,6 +111,7 @@ const ckb: Translations = {
citizen: 'هاوڵاتی',
staking: 'ستەیکینگ',
stakingNotStarted: 'دەستپێنەکراوە',
stakingWaitingData: 'چاوەڕوانی داتا...',
stakingCountedInTrust: 'لە خاڵی متمانە ژمێردراوە',
people: '{count} کەس',
tiki: 'تیکی',
+1
View File
@@ -110,6 +110,7 @@ const en: Translations = {
citizen: 'Citizen',
staking: 'Staking',
stakingNotStarted: 'Not started',
stakingWaitingData: 'Waiting for data...',
stakingCountedInTrust: 'Counted in Trust score',
people: '{count} people',
tiki: 'Tiki',
+1
View File
@@ -110,6 +110,7 @@ const fa: Translations = {
citizen: 'شهروند',
staking: 'سهام‌گذاری',
stakingNotStarted: 'شروع نشده',
stakingWaitingData: 'در انتظار داده‌ها...',
stakingCountedInTrust: 'در امتیاز اعتماد محاسبه می‌شود',
people: '{count} نفر',
tiki: 'تیکی',
+1
View File
@@ -114,6 +114,7 @@ const krd: Translations = {
citizen: 'Welat\u00ee',
staking: 'Staking',
stakingNotStarted: 'Nehat\u00eeye destp\u00eakirin',
stakingWaitingData: 'Li benda daneyan...',
stakingCountedInTrust: 'Di Trust de t\u00ea hesibandin',
people: '{count} kes',
tiki: 'Tiki',
+1
View File
@@ -110,6 +110,7 @@ const tr: Translations = {
citizen: 'Vatandaş',
staking: 'Staking',
stakingNotStarted: 'Başlamadı',
stakingWaitingData: 'Veri bekleniyor...',
stakingCountedInTrust: 'Güven puanına dahil',
people: '{count} kişi',
tiki: 'Tiki',
+1
View File
@@ -112,6 +112,7 @@ export interface Translations {
citizen: string;
staking: string;
stakingNotStarted: string;
stakingWaitingData: string;
stakingCountedInTrust: string;
people: string;
tiki: string;
+48 -3
View File
@@ -28,6 +28,7 @@ export interface UserScores {
export interface StakingScoreStatus {
isTracking: boolean;
hasCachedData: boolean; // Whether noter has submitted staking data
startBlock: number | null;
currentBlock: number;
durationBlocks: number;
@@ -107,7 +108,13 @@ export async function getStakingScoreStatus(
try {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (!(peopleApi?.query as any)?.stakingScore?.stakingStartBlock) {
return { isTracking: false, startBlock: null, currentBlock: 0, durationBlocks: 0 };
return {
isTracking: false,
hasCachedData: false,
startBlock: null,
currentBlock: 0,
durationBlocks: 0,
};
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -115,21 +122,59 @@ export async function getStakingScoreStatus(
const currentBlock = Number((await peopleApi.query.system.number()).toString());
if (startBlockResult.isEmpty || startBlockResult.isNone) {
return { isTracking: false, startBlock: null, currentBlock, durationBlocks: 0 };
return {
isTracking: false,
hasCachedData: false,
startBlock: null,
currentBlock,
durationBlocks: 0,
};
}
const startBlock = Number(startBlockResult.toString());
const durationBlocks = currentBlock - startBlock;
// Check if noter has submitted cached staking data
let hasCachedData = false;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((peopleApi.query as any).stakingScore?.cachedStakingDetails) {
try {
const [relayResult, assetHubResult] = await Promise.all([
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(peopleApi.query as any).stakingScore
.cachedStakingDetails(address, 'RelayChain')
.catch(() => ({ isSome: false, isEmpty: true })),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(peopleApi.query as any).stakingScore
.cachedStakingDetails(address, 'AssetHub')
.catch(() => ({ isSome: false, isEmpty: true })),
]);
hasCachedData =
relayResult.isSome ||
!relayResult.isEmpty ||
assetHubResult.isSome ||
!assetHubResult.isEmpty;
} catch {
hasCachedData = false;
}
}
return {
isTracking: true,
hasCachedData,
startBlock,
currentBlock,
durationBlocks,
};
} catch (error) {
console.error('Error fetching staking score status:', error);
return { isTracking: false, startBlock: null, currentBlock: 0, durationBlocks: 0 };
return {
isTracking: false,
hasCachedData: false,
startBlock: null,
currentBlock: 0,
durationBlocks: 0,
};
}
}
+10 -4
View File
@@ -609,10 +609,16 @@ export function RewardsSection() {
</div>
<p className="text-2xl font-bold text-blue-400">
{stakingStatus?.isTracking ? (
<span className="flex items-center gap-1">
<Clock className="w-4 h-4" />
{formatDuration(stakingStatus.durationBlocks)}
</span>
stakingStatus.hasCachedData ? (
<span className="flex items-center gap-1">
<Clock className="w-4 h-4" />
{formatDuration(stakingStatus.durationBlocks)}
</span>
) : (
<span className="text-sm text-yellow-400">
{t('rewards.stakingWaitingData')}
</span>
)
) : (
<span className="text-sm text-muted-foreground">
{t('rewards.stakingNotStarted')}
+3 -3
View File
@@ -1,5 +1,5 @@
{
"version": "1.0.202",
"buildTime": "2026-02-15T22:27:40.363Z",
"buildNumber": 1771194460364
"version": "1.0.205",
"buildTime": "2026-02-16T22:56:49.789Z",
"buildNumber": 1771282609790
}
+2 -2
View File
@@ -1,8 +1,8 @@
/**
* PezkuwiChain Telegram Bot - Supabase Edge Function
* Handles webhook updates from two separate bots:
* - @Pezkuwichain_Bot (main) → telegram.pezkuwichain.io
* - @pezkuwichainBot (krd) → telegram.pezkiwi.app
* - @Pezkuwichain_Bot (main) → telegram.pezkuwichain.io
* - @pezkuwichainBot (krd) → telegram.pezkiwi.app
*/
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';