diff --git a/shared/lib/citizenship-workflow.ts b/shared/lib/citizenship-workflow.ts index 01ff6e82..6d1eea12 100644 --- a/shared/lib/citizenship-workflow.ts +++ b/shared/lib/citizenship-workflow.ts @@ -4,7 +4,7 @@ // Handles citizenship verification, status checks, and workflow logic import type { ApiPromise } from '@pezkuwi/api'; -import { web3FromAddress as web3FromAddressOriginal } from '@pezkuwi/extension-dapp'; +import { web3Enable, web3FromAddress as web3FromAddressOriginal } from '@pezkuwi/extension-dapp'; import type { InjectedAccountWithMeta } from '@pezkuwi/extension-inject/types'; import type { Signer } from '@pezkuwi/api/types'; @@ -30,7 +30,8 @@ interface InjectedExtension { // Use real extension in browser, throw error in unsupported environments const web3FromAddress = async (address: string): Promise => { // Check if we're in a browser environment with extension support - if (typeof window !== 'undefined' && (window as any).injectedWeb3) { + if (typeof window !== 'undefined') { + await web3Enable('PezkuwiChain'); return web3FromAddressOriginal(address) as Promise; } throw new Error('Pezkuwi Wallet extension not available. Please install the extension.'); diff --git a/web/src/components/AddLiquidityModal.tsx b/web/src/components/AddLiquidityModal.tsx index a69300b4..9113cbc3 100644 --- a/web/src/components/AddLiquidityModal.tsx +++ b/web/src/components/AddLiquidityModal.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import { X, Plus, Info, AlertCircle } from 'lucide-react'; -import { web3FromAddress } from '@pezkuwi/extension-dapp'; +import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp'; import { usePezkuwi } from '@/contexts/PezkuwiContext'; import { useWallet } from '@/contexts/WalletContext'; import { Button } from '@/components/ui/button'; @@ -358,6 +358,7 @@ export const AddLiquidityModal: React.FC = ({ } // Get the signer from the extension + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); // Convert amounts to proper decimals diff --git a/web/src/components/AppLayout.tsx b/web/src/components/AppLayout.tsx index 9d4208b3..6962c206 100644 --- a/web/src/components/AppLayout.tsx +++ b/web/src/components/AppLayout.tsx @@ -178,35 +178,14 @@ const AppLayout: React.FC = () => { {t('nav.beCitizen')} - {/* Governance (dropdown) */} -
- - {openMenu === 'governance' && ( -
- - - - - -
- )} -
+ {/* Settings */} + {/* Trading (dropdown) */}
- {/* Settings */} - + {/* Governance (dropdown) */} +
+ + {openMenu === 'governance' && ( +
+ + + + + +
+ )} +
{/* Logout */}
- +

{t('tokenSwap.liquidityPools')} @@ -1165,7 +1166,7 @@ const TokenSwap = () => { -
+

diff --git a/web/src/components/TransferModal.tsx b/web/src/components/TransferModal.tsx index b37d9688..494133b9 100644 --- a/web/src/components/TransferModal.tsx +++ b/web/src/components/TransferModal.tsx @@ -130,7 +130,8 @@ export const TransferModal: React.FC = ({ isOpen, onClose, s try { // Import web3FromAddress to get the injector - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); + const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp'); + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); // Convert amount to smallest unit diff --git a/web/src/components/USDTBridge.tsx b/web/src/components/USDTBridge.tsx index 8ed9604e..242d9674 100644 --- a/web/src/components/USDTBridge.tsx +++ b/web/src/components/USDTBridge.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { X, ArrowDown, ArrowUp, AlertCircle, Info, Clock, CheckCircle2 } from 'lucide-react'; -import { web3FromAddress } from '@pezkuwi/extension-dapp'; +import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp'; import { usePezkuwi } from '@/contexts/PezkuwiContext'; import { useWallet } from '@/contexts/WalletContext'; import { Button } from '@/components/ui/button'; @@ -114,6 +114,7 @@ export const USDTBridge: React.FC = ({ setSuccess(null); try { + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); // Burn wUSDT diff --git a/web/src/components/XCMTeleportModal.tsx b/web/src/components/XCMTeleportModal.tsx index b9dc9192..0e530548 100644 --- a/web/src/components/XCMTeleportModal.tsx +++ b/web/src/components/XCMTeleportModal.tsx @@ -157,7 +157,8 @@ export const XCMTeleportModal: React.FC = ({ isOpen, onCl setTxStatus('signing'); try { - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); + const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp'); + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); // Convert to smallest unit (12 decimals) diff --git a/web/src/components/admin/CommissionSetupTab.tsx b/web/src/components/admin/CommissionSetupTab.tsx index 66f91fd7..dc4b2630 100644 --- a/web/src/components/admin/CommissionSetupTab.tsx +++ b/web/src/components/admin/CommissionSetupTab.tsx @@ -70,7 +70,8 @@ export function CommissionSetupTab() { setProcessing(true); try { - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); + const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp'); + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); // Parse addresses (one per line, trim whitespace) @@ -174,7 +175,8 @@ export function CommissionSetupTab() { setProcessing(true); try { - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); + const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp'); + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); if (import.meta.env.DEV) console.log('Initializing KYC Commission...'); diff --git a/web/src/components/admin/CommissionVotingTab.tsx b/web/src/components/admin/CommissionVotingTab.tsx index 63da1ef2..51fedf87 100644 --- a/web/src/components/admin/CommissionVotingTab.tsx +++ b/web/src/components/admin/CommissionVotingTab.tsx @@ -150,7 +150,8 @@ export function CommissionVotingTab() { setVoting(proposal.hash); try { - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); + const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp'); + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); if (import.meta.env.DEV) console.log(`Voting ${approve ? 'AYE' : 'NAY'} on proposal:`, proposal.hash); @@ -257,7 +258,8 @@ export function CommissionVotingTab() { setVoting(proposal.hash); try { - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); + const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp'); + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); if (import.meta.env.DEV) console.log('Executing proposal:', proposal.hash); @@ -431,7 +433,8 @@ export function CommissionVotingTab() { if (!api || !selectedAccount) return; try { - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); + const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp'); + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); // Get current members diff --git a/web/src/components/dashboard/CommissionProposalsCard.tsx b/web/src/components/dashboard/CommissionProposalsCard.tsx index d09c8906..cf711b7b 100644 --- a/web/src/components/dashboard/CommissionProposalsCard.tsx +++ b/web/src/components/dashboard/CommissionProposalsCard.tsx @@ -109,7 +109,8 @@ export function CommissionProposalsCard() { setVoting(proposal.hash); try { - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); + const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp'); + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); const tx = api.tx.dynamicCommissionCollective.vote( @@ -199,7 +200,8 @@ export function CommissionProposalsCard() { setVoting(proposal.hash); try { - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); + const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp'); + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); // Get proposal length bound diff --git a/web/src/components/dex/DEXDashboard.tsx b/web/src/components/dex/DEXDashboard.tsx index 09290a44..2b3c1b37 100644 --- a/web/src/components/dex/DEXDashboard.tsx +++ b/web/src/components/dex/DEXDashboard.tsx @@ -50,14 +50,14 @@ export const DEXDashboard: React.FC = () => { }; return ( -
+
{/* Header */} -
+
-

+

{t('dex.title')}

-

+

{t('dex.description')}

diff --git a/web/src/components/p2p/P2PDashboard.tsx b/web/src/components/p2p/P2PDashboard.tsx index 4743ab23..13bff1c8 100644 --- a/web/src/components/p2p/P2PDashboard.tsx +++ b/web/src/components/p2p/P2PDashboard.tsx @@ -131,8 +131,26 @@ export function P2PDashboard() { />
- {/* Stats Cards */} -
+ {/* Stats Cards - Compact on mobile */} +
+
+ + {t('p2p.activeTrades')} + {userStats.activeTrades} +
+
+ + {t('p2p.completed')} + {userStats.completedTrades} +
+
+ + {t('p2p.volume')} + ${userStats.totalVolume.toLocaleString()} +
+
+ {/* Stats Cards - Desktop */} +
diff --git a/web/src/components/referral/InviteUserModal.tsx b/web/src/components/referral/InviteUserModal.tsx index 3e71ce89..0c3645ab 100644 --- a/web/src/components/referral/InviteUserModal.tsx +++ b/web/src/components/referral/InviteUserModal.tsx @@ -81,7 +81,8 @@ export const InviteUserModal: React.FC = ({ isOpen, onClos setInitiateSuccess(false); try { - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); + const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp'); + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); if (import.meta.env.DEV) console.log(`Initiating referral from ${selectedAccount.address} to ${inviteeAddress}...`); diff --git a/web/src/components/referral/ReferralDashboard.tsx b/web/src/components/referral/ReferralDashboard.tsx index 201c8991..658ed52b 100644 --- a/web/src/components/referral/ReferralDashboard.tsx +++ b/web/src/components/referral/ReferralDashboard.tsx @@ -100,8 +100,27 @@ export const ReferralDashboard: React.FC = () => {
- {/* Stats Grid */} -
+ {/* Mobile Compact Stats */} +
+
+ + {t('referral.totalReferrals')} + {stats?.referralCount ?? 0} +
+
+ + {t('referral.referralScore')} + {stats?.referralScore ?? 0} +
+
+ + {t('referral.pendingApprovals')} + {loadingApprovals ? '...' : pendingApprovals.length} +
+
+ + {/* Desktop Stats Grid */} +
{/* Referral Count */} @@ -165,8 +184,8 @@ export const ReferralDashboard: React.FC = () => {
- {/* Score Breakdown */} - + {/* Score Breakdown - Desktop only */} + {t('referral.scoreCalc')} diff --git a/web/src/contexts/WalletContext.tsx b/web/src/contexts/WalletContext.tsx index d9859c12..ddcb93b3 100644 --- a/web/src/contexts/WalletContext.tsx +++ b/web/src/contexts/WalletContext.tsx @@ -9,7 +9,7 @@ import { usePezkuwi } from './PezkuwiContext'; import { WALLET_ERRORS, formatBalance, ASSET_IDS } from '@pezkuwi/lib/wallet'; import type { InjectedAccountWithMeta } from '@pezkuwi/extension-inject/types'; import type { Signer } from '@pezkuwi/api/types'; -import { web3FromAddress } from '@pezkuwi/extension-dapp'; +import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp'; import { isMobileApp, signTransactionNative, type TransactionPayload } from '@/lib/mobile-bridge'; import { createWCSigner, isWCConnected, validateSession } from '@/lib/walletconnect-service'; @@ -275,8 +275,9 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr } // Desktop / pezWallet DApps browser: Use extension signer - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); - const injector = await web3FromAddress(pezkuwi.selectedAccount.address); + const { web3Enable: enable, web3FromAddress: fromAddress } = await import('@pezkuwi/extension-dapp'); + await enable('PezkuwiChain'); + const injector = await fromAddress(pezkuwi.selectedAccount.address); const hash = await (tx as { signAndSend: (address: string, options: { signer: unknown }) => Promise<{ toHex: () => string }> }).signAndSend( pezkuwi.selectedAccount.address, @@ -317,8 +318,9 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr } // Extension signing - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); - const injector = await web3FromAddress(pezkuwi.selectedAccount.address); + const { web3Enable: enable, web3FromAddress: fromAddress } = await import('@pezkuwi/extension-dapp'); + await enable('PezkuwiChain'); + const injector = await fromAddress(pezkuwi.selectedAccount.address); if (!injector.signer.signRaw) { throw new Error('Wallet does not support message signing'); @@ -352,6 +354,7 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr setSigner(wcSigner as unknown as Signer); if (import.meta.env.DEV) console.log('✅ WC Signer obtained for', pezkuwi.selectedAccount.address); } else if (pezkuwi.walletSource !== 'walletconnect') { + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(pezkuwi.selectedAccount.address); setSigner(injector.signer); if (import.meta.env.DEV) console.log('✅ Extension Signer obtained for', pezkuwi.selectedAccount.address); diff --git a/web/src/pages/Dashboard.tsx b/web/src/pages/Dashboard.tsx index 86f521df..2a4c09f2 100644 --- a/web/src/pages/Dashboard.tsx +++ b/web/src/pages/Dashboard.tsx @@ -12,7 +12,7 @@ import { User, Mail, Phone, Globe, MapPin, Calendar, Shield, AlertCircle, ArrowL import { useToast } from '@/hooks/use-toast'; import { fetchUserTikis, getPrimaryRole, getTikiDisplayName, getTikiColor, getTikiEmoji, getUserRoleCategories, getAllTikiNFTDetails, generateCitizenNumber, type TikiNFTDetails } from '@pezkuwi/lib/tiki'; import { getAllScores, getStakingScoreStatus, startScoreTracking, getPezRewards, recordTrustScore, claimPezReward, type UserScores, type StakingScoreStatus, type PezRewardInfo, formatDuration } from '@pezkuwi/lib/scores'; -import { web3FromAddress } from '@pezkuwi/extension-dapp'; +import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp'; import { getKycStatus } from '@pezkuwi/lib/kyc'; import { ReferralDashboard } from '@/components/referral/ReferralDashboard'; // Commission proposals card removed - no longer using notary system for KYC approval @@ -157,6 +157,7 @@ export default function Dashboard() { setStartingScoreTracking(true); try { + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); // startScoreTracking on People Chain - staking data comes from Asset Hub via XCM const result = await startScoreTracking(peopleApi, selectedAccount.address, injector.signer); @@ -192,6 +193,7 @@ export default function Dashboard() { setIsRecordingScore(true); try { + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); const result = await recordTrustScore(peopleApi, selectedAccount.address, injector.signer); @@ -213,6 +215,7 @@ export default function Dashboard() { setIsClaimingReward(true); try { + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); const result = await claimPezReward(peopleApi, selectedAccount.address, epochIndex, injector.signer); @@ -329,7 +332,8 @@ export default function Dashboard() { setRenouncingCitizenship(true); try { - const { web3FromAddress } = await import('@pezkuwi/extension-dapp'); + const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp'); + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); if (import.meta.env.DEV) console.log('Renouncing citizenship...'); @@ -411,16 +415,19 @@ export default function Dashboard() { } return ( -
- -

{t('dashboard.title')}

+
+
+ +

{t('dashboard.title')}

+
-
+ {/* Account Status, Member Since, Role, Total Score - desktop only */} +
{t('dashboard.accountStatus')} @@ -488,7 +495,59 @@ export default function Dashboard() {
-
+ {/* Scores - compact 2x2 grid on mobile, full cards on desktop */} +
+
+ +
+

{t('dashboard.trustScore')}

+

{loadingScores ? '...' : scores.trustScore}

+
+
+
+ +
+

{t('dashboard.referralScore')}

+

{loadingScores ? '...' : scores.referralScore}

+
+
+
+ +
+

{t('dashboard.stakingScore')}

+

{loadingScores ? '...' : scores.stakingScore}

+
+
+
+ +
+

{t('dashboard.tikiScore')}

+

{loadingScores ? '...' : scores.tikiScore}

+
+
+
+ + {/* Staking Start Tracking - mobile only, separate card */} + {!stakingStatus?.isTracking && selectedAccount && ( +
+ +
+ )} + + {/* Scores - full cards on desktop */} +
{t('dashboard.trustScore')} @@ -664,7 +723,7 @@ export default function Dashboard() { {t('dashboard.rolesTab')} {t('dashboard.referralsTab')} {t('dashboard.securityTab')} - {t('dashboard.activityTab')} + {t('dashboard.activityTab')} diff --git a/web/src/pages/Presale.tsx b/web/src/pages/Presale.tsx index 9180cf50..c245e79a 100644 --- a/web/src/pages/Presale.tsx +++ b/web/src/pages/Presale.tsx @@ -7,11 +7,13 @@ import { Input } from '@/components/ui/input'; import { Card } from '@/components/ui/card'; import { Progress } from '@/components/ui/progress'; import { Alert, AlertDescription } from '@/components/ui/alert'; -import { Loader2, AlertCircle, CheckCircle2, Timer, TrendingUp, Users } from 'lucide-react'; +import { Loader2, AlertCircle, CheckCircle2, Timer, TrendingUp, Users, ArrowLeft } from 'lucide-react'; +import { useNavigate } from 'react-router-dom'; import { toast } from 'sonner'; export default function Presale() { const { t } = useTranslation(); + const navigate = useNavigate(); const { api, selectedAccount, isApiReady } = usePezkuwi(); const { balances } = useWallet(); @@ -163,6 +165,17 @@ export default function Presale() { if (!active) { return (
+
+
+ + Back +
+
@@ -199,13 +212,21 @@ export default function Presale() { return (
-
-

- PEZ Token Pre-Sale -

-

- Contribute wUSDT and receive PEZ tokens at a special rate -

+
+ +
+

+ PEZ Token Pre-Sale +

+

+ Contribute wUSDT and receive PEZ tokens at a special rate +

+
{paused && ( diff --git a/web/src/pages/ProfileSettings.tsx b/web/src/pages/ProfileSettings.tsx index a1ab62e9..09a4be93 100644 --- a/web/src/pages/ProfileSettings.tsx +++ b/web/src/pages/ProfileSettings.tsx @@ -212,14 +212,16 @@ export default function ProfileSettings() { }; return ( -
- -

{t('profileSettings.title')}

+
+
+ +

{t('profileSettings.title')}

+
diff --git a/web/src/pages/WalletDashboard.tsx b/web/src/pages/WalletDashboard.tsx index 47c83a40..53891140 100644 --- a/web/src/pages/WalletDashboard.tsx +++ b/web/src/pages/WalletDashboard.tsx @@ -10,7 +10,7 @@ import { NftList } from '@/components/NftList'; import { Button } from '@/components/ui/button'; import { ArrowUpRight, ArrowDownRight, History, ArrowLeft, RefreshCw, Coins, Loader2 } from 'lucide-react'; import { toast } from 'sonner'; -import { web3FromAddress } from '@pezkuwi/extension-dapp'; +import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp'; import { getPezRewards, recordTrustScore, claimPezReward, type PezRewardInfo } from '@pezkuwi/lib/scores'; interface Transaction { @@ -239,6 +239,7 @@ const WalletDashboard: React.FC = () => { if (!peopleApi || !selectedAccount) return; setIsRecordingScore(true); try { + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); const result = await recordTrustScore(peopleApi, selectedAccount.address, injector.signer); if (result.success) { @@ -259,6 +260,7 @@ const WalletDashboard: React.FC = () => { if (!peopleApi || !selectedAccount) return; setIsClaimingReward(true); try { + await web3Enable('PezkuwiChain'); const injector = await web3FromAddress(selectedAccount.address); const result = await claimPezReward(peopleApi, selectedAccount.address, epochIndex, injector.signer); if (result.success) { @@ -299,20 +301,22 @@ const WalletDashboard: React.FC = () => { return (
- -
-

{t('wallet.dashboard')}

-

{t('wallet.manageTokens')}

+
+ +
+

{t('wallet.dashboard')}

+

{t('wallet.manageTokens')}

+
- {/* Left Column - Recent Activity & NFTs */} -
+ {/* Left Column - Recent Activity & NFTs (hidden on mobile) */} +
{/* Recent Activity */}