auto-commit for 70834f3c-ff5c-499f-8170-d839119c1795

This commit is contained in:
emergent-agent-e1
2025-11-08 10:25:19 +00:00
parent f21c48903f
commit 93507ec91b
+74 -155
View File
@@ -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<void>;
disconnectWallet: () => Promise<void>;
// State
disconnectWallet: () => void;
error: string | null;
isLoading: boolean;
}
const PolkadotContext = createContext<PolkadotContextType | undefined>(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<PolkadotProviderProps> = ({
}) => {
const [api, setApi] = useState<any | null>(null);
const [isApiReady, setIsApiReady] = useState(false);
const [accounts, setAccounts] = useState<ConnectedAccount[]>([]);
const [selectedAccount, setSelectedAccount] = useState<ConnectedAccount | null>(null);
const [accounts, setAccounts] = useState<Account[]>([]);
const [selectedAccount, setSelectedAccount] = useState<Account | null>(null);
const [error, setError] = useState<string | null>(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<PolkadotProviderProps> = ({
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<PolkadotProviderProps> = ({
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<PolkadotProviderProps> = ({
};
}, [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 (
<PolkadotContext.Provider value={value}>
<WalletConnectModal
projectId={projectId}
providerMetadata={providerMetadata}
onSessionUpdate={handleSessionUpdate}
/>
{children}
</PolkadotContext.Provider>
);