- {/* Epoch Rewards */}
- {stakingInfo?.pezRewards && stakingInfo.pezRewards.hasPendingClaim && (
-
-
-
- Epoch Rewards
-
-
-
-
- Current Epoch
-
- #{stakingInfo.pezRewards.currentEpoch}
-
-
-
- Claimable
-
- {stakingInfo.pezRewards.totalClaimable} PEZ
-
-
-
-
-
- {stakingInfo.pezRewards.claimableRewards.map(reward => (
-
-
-
Epoch #{reward.epoch}
-
{reward.amount} PEZ
-
-
-
- ))}
-
+ {/* Referral Link */}
+
+
Referans Linkin
+
+ {referralLink}
+
- )}
+
- {/* Daily Tasks */}
-
-
-
- Daily Tasks
+
+
+
+
+
+ {/* Score System Info */}
+
+
+
+
+
+ Puan Sistemi
+
+
+
+
+
+ 1-10 referans
+
+
×10 puan
+
+
+
+ 11-50 referans
+
+
100 + ×5 puan
+
+
+
+ 51-100 referans
+
+
300 + ×4 puan
+
+
+
+ 101+ referans
+
+
500 (Max)
+
+
+
+
+
+ {/* Epoch Rewards */}
+ {stakingInfo?.pezRewards?.hasPendingClaim && (
+
+
+
+
+
+
+ Epoch Ödülleri
+
+
+ Epoch #{stakingInfo.pezRewards.currentEpoch}
+
-
- {dailyTasks.map(task => (
-
-
-
-
- {task.title}
-
- {task.completed && (
-
- )}
-
-
{task.description}
-
-
- +{task.reward} pts
-
+
+
Bekleyen PEZ
+
+ {stakingInfo.pezRewards.totalClaimable} PEZ
+
+
+
+
+ {stakingInfo.pezRewards.claimableRewards.map((reward) => (
+
+ Epoch #{reward.epoch}
+ {reward.amount} PEZ
))}
-
- >
- )}
-
+
+
+
+
+
+ )}
+
+ {/* My Referrals List */}
+ {myReferrals && myReferrals.length > 0 && (
+
+
+
+
+
+ Referanslarım ({myReferrals.length})
+
+
+
+ {myReferrals.slice(0, 5).map((referral, index) => (
+
+
+
+ {index + 1}
+
+
+ {referral.slice(0, 6)}...{referral.slice(-4)}
+
+
+
+ KYC Onaylı
+
+
+ ))}
+ {myReferrals.length > 5 && (
+
+ +{myReferrals.length - 5} daha fazla
+
+ )}
+
+
+
+ )}
+
+ {/* Who invited me */}
+ {stats?.whoInvitedMe && (
+
+
+
+
+ Davet eden:
+
+ {stats.whoInvitedMe.slice(0, 8)}...{stats.whoInvitedMe.slice(-6)}
+
+
+
+
+ )}
);
}
-export default Rewards;
+export default RewardsSection;
diff --git a/web/src/telegram/components/Sidebar.tsx b/web/src/telegram/components/Sidebar.tsx
deleted file mode 100644
index efb89737..00000000
--- a/web/src/telegram/components/Sidebar.tsx
+++ /dev/null
@@ -1,124 +0,0 @@
-import { cn } from '@/lib/utils';
-import { useTelegram } from '../hooks/useTelegram';
-import {
- Megaphone,
- MessageCircle,
- Gift,
- Smartphone,
- Wallet
-} from 'lucide-react';
-
-export type Section = 'announcements' | 'forum' | 'rewards' | 'apk' | 'wallet';
-
-interface SidebarItem {
- id: Section;
- icon: React.ReactNode;
- label: string;
- emoji: string;
-}
-
-const sidebarItems: SidebarItem[] = [
- {
- id: 'announcements',
- icon:
,
- label: 'Duyurular',
- emoji: '📢'
- },
- {
- id: 'forum',
- icon:
,
- label: 'Forum',
- emoji: '💬'
- },
- {
- id: 'rewards',
- icon:
,
- label: 'Rewards',
- emoji: '🎁'
- },
- {
- id: 'apk',
- icon:
,
- label: 'APK',
- emoji: '📱'
- },
- {
- id: 'wallet',
- icon:
,
- label: 'Wallet',
- emoji: '💳'
- },
-];
-
-interface SidebarProps {
- activeSection: Section;
- onSectionChange: (section: Section) => void;
-}
-
-export function Sidebar({ activeSection, onSectionChange }: SidebarProps) {
- const { hapticSelection, isTelegram } = useTelegram();
-
- const handleClick = (section: Section) => {
- if (isTelegram) {
- hapticSelection();
- }
- onSectionChange(section);
- };
-
- return (
-
- {/* Logo at top */}
-
-
- {/* Divider */}
-
-
- {/* Navigation items */}
-
-
- {/* Bottom section - could add settings or user avatar here */}
-
-
- );
-}
-
-export default Sidebar;
diff --git a/web/src/telegram/components/Wallet/index.tsx b/web/src/telegram/components/Wallet/index.tsx
index 61e860f5..983cee4a 100644
--- a/web/src/telegram/components/Wallet/index.tsx
+++ b/web/src/telegram/components/Wallet/index.tsx
@@ -1,98 +1,45 @@
import { useState, useEffect } from 'react';
-import { Wallet as WalletIcon, Send, ArrowDownToLine, RefreshCw, Copy, Check, Loader2, TrendingUp, Clock, ExternalLink } from 'lucide-react';
-import { useTelegram } from '../../hooks/useTelegram';
-import { usePezkuwiApi } from '../../hooks/usePezkuwiApi';
import { usePezkuwi } from '@/contexts/PezkuwiContext';
-import { formatBalance, CHAIN_CONFIG, formatAddress } from '@shared/lib/wallet';
+import { useWallet } from '@/contexts/WalletContext';
+import { useTelegram } from '../../hooks/useTelegram';
+import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
+import { Button } from '@/components/ui/button';
+import { Badge } from '@/components/ui/badge';
+import { Skeleton } from '@/components/ui/skeleton';
+import { getAllScores, UserScores, getScoreRating } from '@shared/lib/scores';
import { getStakingInfo, StakingInfo } from '@shared/lib/staking';
+import { formatBalance, formatAddress, CHAIN_CONFIG } from '@shared/lib/wallet';
+import {
+ Wallet, Send, ArrowDownToLine, TrendingUp, Copy, Check, ExternalLink,
+ Loader2, RefreshCw, Trophy, Users, Star, Award, Coins, Clock, Zap
+} from 'lucide-react';
import { cn } from '@/lib/utils';
-interface TokenBalance {
- symbol: string;
- name: string;
- balance: string;
- balanceUsd?: string;
- icon?: string;
- isNative?: boolean;
-}
-
-interface Transaction {
- id: string;
- type: 'send' | 'receive' | 'stake' | 'unstake' | 'claim';
- amount: string;
- symbol: string;
- address?: string;
- timestamp: Date;
- status: 'pending' | 'confirmed' | 'failed';
-}
-
-// Mock recent transactions - will be replaced with actual data
-const mockTransactions: Transaction[] = [
- {
- id: '1',
- type: 'receive',
- amount: '100.00',
- symbol: 'HEZ',
- address: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
- timestamp: new Date(Date.now() - 1000 * 60 * 60 * 2),
- status: 'confirmed',
- },
- {
- id: '2',
- type: 'stake',
- amount: '50.00',
- symbol: 'HEZ',
- timestamp: new Date(Date.now() - 1000 * 60 * 60 * 24),
- status: 'confirmed',
- },
- {
- id: '3',
- type: 'claim',
- amount: '5.25',
- symbol: 'PEZ',
- timestamp: new Date(Date.now() - 1000 * 60 * 60 * 24 * 3),
- status: 'confirmed',
- },
-];
-
-export function Wallet() {
+export function WalletSection() {
+ const { api, isApiReady, selectedAccount, connectWallet, disconnectWallet, accounts } = usePezkuwi();
+ const { balances, refreshBalances, isConnected } = useWallet();
const { hapticNotification, hapticImpact, showAlert, openLink } = useTelegram();
- const { api, isReady: isApiReady } = usePezkuwiApi();
- const { selectedAccount, connectWallet, disconnectWallet } = usePezkuwi();
- const [balances, setBalances] = useState
([]);
+ const [scores, setScores] = useState(null);
const [stakingInfo, setStakingInfo] = useState(null);
- const [transactions, setTransactions] = useState(mockTransactions);
const [isLoading, setIsLoading] = useState(false);
const [isRefreshing, setIsRefreshing] = useState(false);
const [copied, setCopied] = useState(false);
- const isConnected = !!selectedAccount;
const address = selectedAccount?.address;
- // Fetch balances when connected
+ // Fetch data when connected
useEffect(() => {
if (!api || !isApiReady || !address) return;
const fetchData = async () => {
setIsLoading(true);
try {
- // Fetch native balance
- const accountInfo = await api.query.system.account(address);
- const { data } = accountInfo.toJSON() as { data: { free: string; reserved: string } };
- const freeBalance = BigInt(data.free || 0);
-
- const nativeBalance: TokenBalance = {
- symbol: CHAIN_CONFIG.symbol,
- name: 'Hezar Token',
- balance: formatBalance(freeBalance.toString()),
- isNative: true,
- };
-
- setBalances([nativeBalance]);
-
- // Fetch staking info
- const staking = await getStakingInfo(api, address);
+ const [userScores, staking] = await Promise.all([
+ getAllScores(api, address),
+ getStakingInfo(api, address),
+ ]);
+ setScores(userScores);
setStakingInfo(staking);
} catch (err) {
console.error('Failed to fetch wallet data:', err);
@@ -106,26 +53,19 @@ export function Wallet() {
const handleRefresh = async () => {
if (!api || !address || isRefreshing) return;
-
setIsRefreshing(true);
hapticNotification('success');
try {
- const accountInfo = await api.query.system.account(address);
- const { data } = accountInfo.toJSON() as { data: { free: string } };
- const freeBalance = BigInt(data.free || 0);
-
- setBalances([{
- symbol: CHAIN_CONFIG.symbol,
- name: 'Hezar Token',
- balance: formatBalance(freeBalance.toString()),
- isNative: true,
- }]);
-
- const staking = await getStakingInfo(api, address);
+ await refreshBalances();
+ const [userScores, staking] = await Promise.all([
+ getAllScores(api, address),
+ getStakingInfo(api, address),
+ ]);
+ setScores(userScores);
setStakingInfo(staking);
} catch (err) {
- showAlert('Failed to refresh');
+ showAlert('Yenileme başarısız');
} finally {
setIsRefreshing(false);
}
@@ -133,14 +73,13 @@ export function Wallet() {
const handleCopyAddress = async () => {
if (!address) return;
-
try {
await navigator.clipboard.writeText(address);
setCopied(true);
hapticNotification('success');
setTimeout(() => setCopied(false), 2000);
} catch {
- showAlert('Failed to copy address');
+ showAlert('Adres kopyalanamadı');
}
};
@@ -149,273 +88,307 @@ export function Wallet() {
connectWallet();
};
- const handleDisconnect = () => {
- hapticImpact('medium');
- disconnectWallet();
- };
-
const handleOpenExplorer = () => {
if (!address) return;
hapticImpact('light');
openLink(`https://explorer.pezkuwichain.io/account/${address}`);
};
- const getTransactionIcon = (type: Transaction['type']) => {
- switch (type) {
- case 'send':
- return ;
- case 'receive':
- return ;
- case 'stake':
- return ;
- case 'unstake':
- return ;
- case 'claim':
- return ;
- default:
- return null;
- }
- };
-
- const formatTimestamp = (date: Date) => {
- const now = new Date();
- const diff = now.getTime() - date.getTime();
- const hours = Math.floor(diff / (1000 * 60 * 60));
- const days = Math.floor(hours / 24);
-
- if (hours < 1) return 'Just now';
- if (hours < 24) return `${hours}h ago`;
- if (days < 7) return `${days}d ago`;
- return date.toLocaleDateString('tr-TR', { day: 'numeric', month: 'short' });
- };
-
- if (!isConnected) {
+ // Not connected state
+ if (!isConnected || !selectedAccount) {
return (
-
-
-
-
Wallet
-
+
-
-
+
+
-
Connect Your Wallet
-
- Connect your Pezkuwi wallet to view balances, stake tokens, and manage your assets.
+
Cüzdanınızı Bağlayın
+
+ Bakiyelerinizi görüntülemek, stake etmek ve işlem yapmak için Pezkuwi cüzdanınızı bağlayın.
-
+
+ Cüzdan Bağla
+
+
+
+
+
+ HEZ & PEZ
+
+
+
+ Staking
+
+
+
+ Rewards
+
+
);
}
return (
-
- {/* Header */}
-
-
-
-
Wallet
-
-
-
-
-
-
-
- {/* Content */}
-
- {isLoading ? (
-
-
-
- ) : (
- <>
- {/* Address Card */}
-
-
-
-
- {selectedAccount?.meta?.name || 'Account'}
+
+ {/* Account Card */}
+
+
+
+
+
+
+
+ {selectedAccount?.meta?.name?.charAt(0) || 'P'}
-
-
-
- {formatAddress(address || '')}
-
-
+
+
+ {selectedAccount?.meta?.name || 'Pezkuwi Hesabı'}
+
+
+
+ {formatAddress(address || '')}
+
+
+
+
+
+
+
- {/* Balance Card */}
-
-
-
Total Balance
-
- {balances[0]?.balance || '0.00'} {CHAIN_CONFIG.symbol}
+ {/* Balance Display */}
+
+
Toplam Bakiye
+ {isLoading ? (
+
+ ) : (
+
+
+ {balances?.HEZ || '0.00'}
+
+ {CHAIN_CONFIG.symbol}
- {stakingInfo && parseFloat(stakingInfo.bonded) > 0 && (
-
- Staked: {stakingInfo.bonded} {CHAIN_CONFIG.symbol}
-
- )}
-
+ )}
+ {balances?.PEZ && parseFloat(balances.PEZ) > 0 && (
+
+ + {balances.PEZ} PEZ
+
+ )}
{/* Quick Actions */}
-
-
-
-
-
-
+
+
+
+
+
+
+
- {/* Staking Info */}
- {stakingInfo && parseFloat(stakingInfo.bonded) > 0 && (
-
-
-
-
- Staking Overview
-
-
-
-
Bonded
-
{stakingInfo.bonded}
-
-
-
Active
-
{stakingInfo.active}
-
- {stakingInfo.stakingScore !== null && (
-
-
Staking Score
-
{stakingInfo.stakingScore}
-
- )}
-
-
Nominations
-
{stakingInfo.nominations.length}
-
-
+ {/* Scores Section */}
+
+
+
+ Puanlarınız
+
+
+ {isLoading ? (
+
+ {[...Array(4)].map((_, i) => (
+
+ ))}
+
+ ) : scores ? (
+ <>
+ {/* Total Score Banner */}
+
+
+
+
Toplam Skor
+
{scores.totalScore}
-
- )}
+
+ {getScoreRating(scores.totalScore)}
+
+
+
- {/* Recent Transactions */}
-
-
-
-
Recent Activity
-
+ {/* Individual Scores */}
+
+
+
+
+ {scores.trustScore}
+
+
- {transactions.length === 0 ? (
-
- No recent transactions
+
+
+
- ) : (
-
- {transactions.map(tx => (
-
-
-
- {getTransactionIcon(tx.type)}
-
-
-
- {tx.type}
-
-
- {formatTimestamp(tx.timestamp)}
-
-
-
-
-
- {tx.type === 'send' || tx.type === 'stake' ? '-' : '+'}
- {tx.amount} {tx.symbol}
-
-
- {tx.status}
-
-
-
- ))}
+
{scores.referralScore}
+
+
+
+
+
+
- )}
-
+ {scores.stakingScore}
+
+
+
+
+
+
+ {scores.tikiScore}
+
+
>
- )}
+ ) : null}
+
+
+ {/* Staking Info */}
+ {stakingInfo && parseFloat(stakingInfo.bonded) > 0 && (
+
+
+
+ Staking Durumu
+
+
+
+
+
+
+
Stake Edilmiş
+
{stakingInfo.bonded} HEZ
+
+
+
Aktif
+
{stakingInfo.active} HEZ
+
+ {stakingInfo.stakingScore !== null && (
+
+
Staking Skoru
+
{stakingInfo.stakingScore}/100
+
+ )}
+
+
Nominasyonlar
+
{stakingInfo.nominations.length}
+
+
+
+ {/* PEZ Rewards */}
+ {stakingInfo.pezRewards?.hasPendingClaim && (
+
+
+
+
+ Bekleyen PEZ
+
+
+ {stakingInfo.pezRewards.totalClaimable} PEZ
+
+
+
+
+ )}
+
+
+
+ )}
+
+ {/* Disconnect Button */}
+
+
);
}
-export default Wallet;
+export default WalletSection;