diff --git a/frontend/src/contexts/PolkadotContext.tsx b/frontend/src/contexts/PolkadotContext.tsx index 43725cb2..901280aa 100644 --- a/frontend/src/contexts/PolkadotContext.tsx +++ b/frontend/src/contexts/PolkadotContext.tsx @@ -1,79 +1,53 @@ import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react'; import { Platform, Alert } from 'react-native'; -import AsyncStorage from '@react-native-async-storage/async-storage'; import { getCurrentEndpoint, WALLET_ERRORS } from '../lib/wallet'; -// WalletConnect imports -import { WalletConnectModal, useWalletConnectModal } from '@walletconnect/modal-react-native'; - -// Platform-aware Polkadot.js import for reading blockchain data -// Only import on native platforms (not web) +// Platform-aware imports let ApiPromise: any = null; let WsProvider: any = null; if (Platform.OS !== 'web') { + // Native: Use Polkadot.js try { const polkadotApi = require('@polkadot/api'); - ApiPromise = polkadotApi.ApiPromise; WsProvider = polkadotApi.WsProvider; - - console.log('✅ Polkadot.js loaded for reading blockchain data'); + console.log('✅ Polkadot.js loaded (Native)'); } catch (error) { - console.warn('⚠️ Polkadot.js not available:', error); + console.warn('⚠️ Polkadot.js not available'); } +} else { + // Web: Use Polkadot.js (will be imported normally) + const polkadotApi = require('@polkadot/api'); + ApiPromise = polkadotApi.ApiPromise; + WsProvider = polkadotApi.WsProvider; } // ======================================== -// TYPE DEFINITIONS +// TYPES // ======================================== -export interface ConnectedAccount { +export interface Account { address: string; name?: string; - source: 'walletconnect'; + source?: string; } interface PolkadotContextType { - // Blockchain API (read-only) api: any | null; isApiReady: boolean; - - // WalletConnect - isConnected: boolean; - accounts: ConnectedAccount[]; - selectedAccount: ConnectedAccount | null; - - // Actions + accounts: Account[]; + selectedAccount: Account | null; + setSelectedAccount: (account: Account | null) => void; connectWallet: () => Promise; - disconnectWallet: () => Promise; - - // State + disconnectWallet: () => void; error: string | null; - isLoading: boolean; } const PolkadotContext = createContext(undefined); // ======================================== -// WALLETCONNECT CONFIGURATION -// ======================================== - -const projectId = 'e542ff314e26ff34de2d4fba98db70bb'; // PezkuwiChain WalletConnect Project ID - -const providerMetadata = { - name: 'PezkuwiChain', - description: 'Kurdish Digital Citizenship Platform', - url: 'https://www.pezkuwichain.io', - icons: ['https://www.pezkuwichain.io/logo.png'], - redirect: { - native: 'pezkuwichain://', - universal: 'https://www.pezkuwichain.io', - }, -}; - -// ======================================== -// PROVIDER COMPONENT +// PROVIDER // ======================================== interface PolkadotProviderProps { @@ -87,34 +61,23 @@ export const PolkadotProvider: React.FC = ({ }) => { const [api, setApi] = useState(null); const [isApiReady, setIsApiReady] = useState(false); - const [accounts, setAccounts] = useState([]); - const [selectedAccount, setSelectedAccount] = useState(null); + const [accounts, setAccounts] = useState([]); + const [selectedAccount, setSelectedAccount] = useState(null); const [error, setError] = useState(null); - const [isLoading, setIsLoading] = useState(false); - const [isConnected, setIsConnected] = useState(false); const rpcEndpoint = endpoint || getCurrentEndpoint(); - // ======================================== - // BLOCKCHAIN API INITIALIZATION (READ-ONLY) - // ======================================== - + // Initialize Polkadot API (Blockchain RPC connection) useEffect(() => { - if (Platform.OS === 'web') { - console.log('📱 Web platform - using mock mode for blockchain API'); - setIsApiReady(true); - return; - } - const initApi = async () => { try { if (!ApiPromise || !WsProvider) { - console.warn('⚠️ Polkadot.js not available, using mock mode'); - setIsApiReady(true); + console.warn('⚠️ Polkadot.js not available'); + setIsApiReady(false); return; } - console.log('🔗 Connecting to PezkuwiChain RPC:', rpcEndpoint); + console.log('🔗 Connecting to PezkuwiChain:', rpcEndpoint); const provider = new WsProvider(rpcEndpoint); const apiInstance = await ApiPromise.create({ provider }); @@ -125,7 +88,7 @@ export const PolkadotProvider: React.FC = ({ setIsApiReady(true); setError(null); - console.log('✅ Connected to PezkuwiChain for reading blockchain data'); + console.log('✅ Connected to PezkuwiChain'); // Get chain info const [chain, nodeName, nodeVersion] = await Promise.all([ @@ -138,7 +101,7 @@ export const PolkadotProvider: React.FC = ({ console.log(`🖥️ Node: ${nodeName} v${nodeVersion}`); } catch (err: any) { - console.error('❌ Failed to connect to blockchain RPC:', err); + console.error('❌ Failed to connect to node:', err); setError(`Failed to connect: ${rpcEndpoint}`); setIsApiReady(false); } @@ -153,129 +116,85 @@ export const PolkadotProvider: React.FC = ({ }; }, [rpcEndpoint]); - // ======================================== - // WALLETCONNECT: CONNECT WALLET - // ======================================== - + // Connect wallet const connectWallet = async () => { try { setError(null); - setIsLoading(true); if (Platform.OS === 'web') { + // Web: Use Polkadot.js extension + const { web3Accounts, web3Enable } = await import('@polkadot/extension-dapp'); + + const extensions = await web3Enable('PezkuwiChain'); + + if (extensions.length === 0) { + Alert.alert( + 'Extension Required', + 'Please install Polkadot.js extension', + [{ text: 'OK' }] + ); + return; + } + + console.log('✅ Polkadot.js extension enabled'); + + const allAccounts = await web3Accounts(); + + if (allAccounts.length === 0) { + Alert.alert( + 'No Accounts', + 'Please create an account in Polkadot.js extension', + [{ text: 'OK' }] + ); + return; + } + + const mappedAccounts: Account[] = allAccounts.map(acc => ({ + address: acc.address, + name: acc.meta.name, + source: acc.meta.source, + })); + + setAccounts(mappedAccounts); + setSelectedAccount(mappedAccounts[0]); + + console.log(`✅ Connected ${mappedAccounts.length} account(s)`); + + } else { + // Native: Show instruction Alert.alert( - 'Not Available on Web', - 'Please use SubWallet browser extension for web, or use the mobile app.', + 'Wallet Connection', + 'Please enter your wallet address in the app to view your assets. For transactions, you will be guided to SubWallet.', [{ text: 'OK' }] ); - setIsLoading(false); - return; } - - console.log('🔗 Opening WalletConnect modal...'); - - // WalletConnect Modal will handle the connection - // User will see QR code or list of supported wallets (SubWallet, Nova Wallet, etc.) - // This is handled by the WalletConnectModal component in the UI - - Alert.alert( - 'Connect Wallet', - 'Please scan QR code with SubWallet or Nova Wallet mobile app', - [{ text: 'OK' }] - ); - - setIsLoading(false); } catch (err: any) { console.error('❌ Wallet connection failed:', err); setError(WALLET_ERRORS.CONNECTION_FAILED); - setIsLoading(false); } }; - // ======================================== - // WALLETCONNECT: SESSION HANDLER - // ======================================== - - const handleSessionUpdate = (session: any) => { - console.log('✅ WalletConnect session established'); - - // Extract accounts from session - const namespaces = session.namespaces; - const polkadotAccounts = namespaces?.polkadot?.accounts || []; - - const connectedAccounts: ConnectedAccount[] = polkadotAccounts.map((acc: string) => { - // Format: "polkadot:chainId:address" - const parts = acc.split(':'); - const address = parts[parts.length - 1]; - - return { - address, - source: 'walletconnect' as const, - }; - }); - - if (connectedAccounts.length > 0) { - setAccounts(connectedAccounts); - setSelectedAccount(connectedAccounts[0]); - setIsConnected(true); - - // Save session - AsyncStorage.setItem('wc_session', JSON.stringify(session)); - - console.log(`✅ Connected ${connectedAccounts.length} account(s)`); - } + // Disconnect wallet + const disconnectWallet = () => { + setAccounts([]); + setSelectedAccount(null); + console.log('🔌 Wallet disconnected'); }; - // ======================================== - // WALLETCONNECT: DISCONNECT - // ======================================== - - const disconnectWallet = async () => { - try { - setAccounts([]); - setSelectedAccount(null); - setIsConnected(false); - - // Clear session - await AsyncStorage.removeItem('wc_session'); - - console.log('🔌 Wallet disconnected'); - } catch (error) { - console.error('Error disconnecting:', error); - } - }; - - // ======================================== - // CONTEXT VALUE - // ======================================== - const value: PolkadotContextType = { - // Blockchain API (read-only) api, isApiReady, - - // WalletConnect - isConnected, accounts, selectedAccount, - - // Actions + setSelectedAccount, connectWallet, disconnectWallet, - - // State error, - isLoading, }; return ( - {children} );