mirror of
https://github.com/pezkuwichain/pezkuwi-mobile-app.git
synced 2026-06-12 15:51:01 +00:00
auto-commit for 70834f3c-ff5c-499f-8170-d839119c1795
This commit is contained in:
@@ -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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user