refactor(core): Apply various updates and fixes across components

This commit is contained in:
2025-11-19 18:56:38 +03:00
parent bdf59cea47
commit 590ac521e8
21 changed files with 888 additions and 240 deletions
+51 -18
View File
@@ -96,42 +96,75 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
// Check active sessions and sets the user
supabase.auth.getSession().then(({ data: { session } }) => {
setUser(session?.user ?? null);
if (session?.user) {
checkAdminStatus();
}
checkAdminStatus(); // Check admin status regardless of Supabase session
setLoading(false);
}).catch(() => {
// If Supabase is not available, continue without auth
// If Supabase is not available, still check wallet-based admin
checkAdminStatus();
setLoading(false);
});
// Listen for changes on auth state
const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => {
setUser(session?.user ?? null);
if (session?.user) {
checkAdminStatus();
}
checkAdminStatus(); // Check admin status on auth change
setLoading(false);
});
return () => subscription.unsubscribe();
// Listen for wallet changes (from PolkadotContext)
const handleWalletChange = () => {
checkAdminStatus();
};
window.addEventListener('walletChanged', handleWalletChange);
return () => {
subscription.unsubscribe();
window.removeEventListener('walletChanged', handleWalletChange);
};
}, []);
const checkAdminStatus = async () => {
// Admin wallet whitelist (blockchain-based auth)
const ADMIN_WALLETS = [
'5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', // Founder (original)
'5DFwqK698vL4gXHEcanaewnAqhxJ2rjhAogpSTHw3iwGDwd3', // Founder delegate (initial KYC member)
'5GgTgG9sRmPQAYU1RsTejZYnZRjwzKZKWD3awtuqjHioki45', // Founder (current dev wallet)
];
try {
// PRIMARY: Check wallet-based admin (blockchain auth)
const connectedWallet = localStorage.getItem('selectedWallet');
console.log('🔍 Admin check - Connected wallet:', connectedWallet);
console.log('🔍 Admin check - Whitelist:', ADMIN_WALLETS);
if (connectedWallet && ADMIN_WALLETS.includes(connectedWallet)) {
console.log('✅ Admin access granted (wallet-based)');
setIsAdmin(true);
return true;
}
// SECONDARY: Check Supabase admin_roles (if wallet not in whitelist)
const { data: { user } } = await supabase.auth.getUser();
if (!user) return false;
if (user) {
const { data, error } = await supabase
.from('admin_roles')
.select('role')
.eq('user_id', user.id)
.maybeSingle();
const { data, error } = await supabase
.from('admin_roles')
.select('role')
.eq('user_id', user.id)
.maybeSingle();
if (!error && data && ['admin', 'super_admin'].includes(data.role)) {
console.log('✅ Admin access granted (Supabase-based)');
setIsAdmin(true);
return true;
}
}
const adminStatus = !error && data && ['admin', 'super_admin'].includes(data.role);
setIsAdmin(adminStatus);
return adminStatus;
} catch {
console.log('❌ Admin access denied');
setIsAdmin(false);
return false;
} catch (err) {
console.error('Admin check error:', err);
setIsAdmin(false);
return false;
}
};
+62 -11
View File
@@ -33,6 +33,19 @@ export const PolkadotProvider: React.FC<PolkadotProviderProps> = ({
const [selectedAccount, setSelectedAccount] = useState<InjectedAccountWithMeta | null>(null);
const [error, setError] = useState<string | null>(null);
// Wrapper to trigger events when wallet changes
const handleSetSelectedAccount = (account: InjectedAccountWithMeta | null) => {
setSelectedAccount(account);
if (account) {
localStorage.setItem('selectedWallet', account.address);
console.log('💾 Wallet saved:', account.address);
window.dispatchEvent(new Event('walletChanged'));
} else {
localStorage.removeItem('selectedWallet');
window.dispatchEvent(new Event('walletChanged'));
}
};
// Initialize Polkadot API
useEffect(() => {
const initApi = async () => {
@@ -76,35 +89,73 @@ export const PolkadotProvider: React.FC<PolkadotProviderProps> = ({
};
}, [endpoint]);
// Auto-restore wallet on page load
useEffect(() => {
const restoreWallet = async () => {
const savedAddress = localStorage.getItem('selectedWallet');
if (!savedAddress) return;
try {
// Enable extension
const extensions = await web3Enable('PezkuwiChain');
if (extensions.length === 0) return;
// Get accounts
const allAccounts = await web3Accounts();
if (allAccounts.length === 0) return;
// Find saved account
const savedAccount = allAccounts.find(acc => acc.address === savedAddress);
if (savedAccount) {
setAccounts(allAccounts);
handleSetSelectedAccount(savedAccount);
console.log('✅ Wallet restored:', savedAddress.slice(0, 8) + '...');
}
} catch (err) {
console.error('Failed to restore wallet:', err);
}
};
restoreWallet();
}, []);
// Connect wallet (Polkadot.js extension)
const connectWallet = async () => {
try {
setError(null);
// Enable extension
const extensions = await web3Enable('PezkuwiChain');
if (extensions.length === 0) {
setError('Please install Polkadot.js extension');
window.open('https://polkadot.js.org/extension/', '_blank');
return;
}
console.log('✅ Polkadot.js extension enabled');
// Get accounts
const allAccounts = await web3Accounts();
if (allAccounts.length === 0) {
setError('No accounts found. Please create an account in Polkadot.js extension');
return;
}
setAccounts(allAccounts);
setSelectedAccount(allAccounts[0]); // Auto-select first account
// Try to restore previously selected account, otherwise use first
const savedAddress = localStorage.getItem('selectedWallet');
const accountToSelect = savedAddress
? allAccounts.find(acc => acc.address === savedAddress) || allAccounts[0]
: allAccounts[0];
// Use wrapper to trigger events
handleSetSelectedAccount(accountToSelect);
console.log(`✅ Found ${allAccounts.length} account(s)`);
} catch (err) {
console.error('❌ Wallet connection failed:', err);
setError('Failed to connect wallet');
@@ -114,7 +165,7 @@ export const PolkadotProvider: React.FC<PolkadotProviderProps> = ({
// Disconnect wallet
const disconnectWallet = () => {
setAccounts([]);
setSelectedAccount(null);
handleSetSelectedAccount(null);
console.log('🔌 Wallet disconnected');
};
@@ -124,7 +175,7 @@ export const PolkadotProvider: React.FC<PolkadotProviderProps> = ({
isConnected: isApiReady, // Alias for backward compatibility
accounts,
selectedAccount,
setSelectedAccount,
setSelectedAccount: handleSetSelectedAccount,
connectWallet,
disconnectWallet,
error,
+4 -3
View File
@@ -38,9 +38,10 @@ export const WebSocketProvider: React.FC<{ children: React.ReactNode }> = ({ chi
const connectionAttempts = useRef(0);
const ENDPOINTS = [
'wss://ws.pezkuwichain.io', // Production WebSocket
'ws://localhost:9944', // Local development node
'ws://127.0.0.1:9944', // Alternative local address
'ws://localhost:8082', // Local Vite dev server
'ws://127.0.0.1:9944', // Local development node (primary)
'ws://localhost:9944', // Local development node (alternative)
'wss://ws.pezkuwichain.io', // Production WebSocket (fallback)
];
const connect = useCallback((endpointIndex: number = 0) => {