laconic-wallet-web/src/hooks/useWebViewHandler.ts
2025-06-03 17:16:48 +05:30

144 lines
4.5 KiB
TypeScript

import { useEffect, useCallback } from 'react';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { useAccounts } from '../context/AccountsContext';
import { useNetworks } from '../context/NetworksContext';
import { StackParamsList } from '../types';
import useGetOrCreateAccounts from './useGetOrCreateAccounts';
import { retrieveAccountsForNetwork } from '../utils/accounts';
export const useWebViewHandler = () => {
// Navigation and context hooks
const navigation = useNavigation<NativeStackNavigationProp<StackParamsList>>();
const { selectedNetwork } = useNetworks();
const { accounts, currentIndex } = useAccounts();
// Initialize accounts
useGetOrCreateAccounts();
// Core navigation handler
const navigateToSignRequest = useCallback((message: string) => {
try {
// Validation checks
if (!selectedNetwork?.namespace || !selectedNetwork?.chainId) {
window.Android?.onSignatureError?.('Invalid network configuration');
return;
}
if (!accounts?.length) {
window.Android?.onSignatureError?.('No accounts available');
return;
}
const currentAccount = accounts[currentIndex];
if (!currentAccount) {
window.Android?.onSignatureError?.('Current account not found');
return;
}
// Create the path and validate with regex
const path = `/sign/${selectedNetwork.namespace}/${selectedNetwork.chainId}/${currentAccount.address}/${encodeURIComponent(message)}`;
const pathRegex = /^\/sign\/(eip155|cosmos)\/(.+)\/(.+)\/(.+)$/;
const match = path.match(pathRegex);
if (!match) {
window.Android?.onSignatureError?.('Invalid signing path');
return;
}
const [, pathNamespace, pathChainId, pathAddress, pathMessage] = match;
// Reset navigation stack and navigate to sign request
navigation.reset({
index: 0,
routes: [
{
name: 'SignRequest',
path,
params: {
namespace: pathNamespace,
chainId: pathChainId,
address: pathAddress,
message: decodeURIComponent(pathMessage),
accountInfo: currentAccount,
},
},
],
});
} catch (error) {
window.Android?.onSignatureError?.(`Navigation error: ${error}`);
}
}, [selectedNetwork, accounts, currentIndex, navigation]);
// Handle incoming transfer requests
const navigateToTransfer = useCallback(async (to: string, amount: string, namespace: String, chainId: string) => {
const chainSpecs = {
namespace,
chainId,
};
try {
// Get all accounts
const chainAccounts = await retrieveAccountsForNetwork(
`${chainSpecs.namespace}:${chainSpecs.chainId}`,
'0' // Use the first account
);
if (!chainAccounts || chainAccounts.length === 0) {
console.error('Accounts not found');
if (window.Android?.onTransferError) {
window.Android.onTransferError('Accounts not found');
}
return;
}
const chainAccount = chainAccounts[0]; // Use the first account
const path = `/transfer/${chainSpecs.namespace}/${chainSpecs.chainId}/${chainAccount.address}/${to}/${amount}`;
navigation.reset({
index: 0,
routes: [
{
name: 'ApproveTransfer',
path: path,
params: {
namespace: chainSpecs.namespace,
chainId: `${chainSpecs.namespace}:${chainSpecs.chainId}`,
transaction: {
from: chainAccount.address,
to: to,
value: amount,
data: ''
},
accountInfo: chainAccount,
},
},
],
});
} catch (error) {
console.error('Navigation error:', error);
if (window.Android?.onTransferError) {
window.Android.onTransferError(`Navigation error: ${error}`);
}
}
}, [navigation]);
useEffect(() => {
// Assign the function to the window object
window.receiveSignRequestFromAndroid = navigateToSignRequest;
window.receiveTransferRequestFromAndroid = navigateToTransfer;
return () => {
window.receiveSignRequestFromAndroid = undefined;
window.receiveTransferRequestFromAndroid = undefined;
};
}, [navigateToSignRequest, navigateToTransfer]); // Only the function reference as dependency
};