Sign message from app
This commit is contained in:
parent
3a0a321c6f
commit
d9011dbdb2
75
src/components/SignRequestHandler.tsx
Normal file
75
src/components/SignRequestHandler.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
import React, { useState, useEffect } 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 '../hooks/useGetOrCreateAccounts';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
receiveSignRequestFromAndroid?: (message: string) => void;
|
||||
}
|
||||
}
|
||||
|
||||
export const SignRequestHandler: React.FC = () => {
|
||||
const navigation = useNavigation<NativeStackNavigationProp<StackParamsList>>();
|
||||
const { accounts, currentIndex } = useAccounts();
|
||||
const { selectedNetwork } = useNetworks();
|
||||
const [pendingMessage, setPendingMessage] = useState<string | null>(null);
|
||||
|
||||
useGetOrCreateAccounts();
|
||||
|
||||
useEffect(() => {
|
||||
if (pendingMessage && selectedNetwork && accounts && accounts.length > 0) {
|
||||
navigation.reset({
|
||||
index: 0,
|
||||
routes: [
|
||||
{
|
||||
name: 'SignRequest',
|
||||
params: {
|
||||
address: accounts[currentIndex].address,
|
||||
message: pendingMessage,
|
||||
requestEvent: null,
|
||||
path: `/sign/${selectedNetwork.namespace}/${selectedNetwork.chainId}/${accounts[currentIndex].address}/${encodeURIComponent(pendingMessage)}`
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
setPendingMessage(null);
|
||||
}
|
||||
}, [pendingMessage, selectedNetwork, accounts, currentIndex, navigation]);
|
||||
|
||||
useEffect(() => {
|
||||
window.receiveSignRequestFromAndroid = (message: string) => {
|
||||
if (!selectedNetwork || !accounts || accounts.length === 0) {
|
||||
// Store the message and wait for wallet creation
|
||||
setPendingMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
navigation.reset({
|
||||
index: 0,
|
||||
routes: [
|
||||
{
|
||||
name: 'SignRequest',
|
||||
params: {
|
||||
address: accounts[currentIndex].address,
|
||||
message: message,
|
||||
requestEvent: null,
|
||||
path: `/sign/${selectedNetwork.namespace}/${selectedNetwork.chainId}/${accounts[currentIndex].address}/${encodeURIComponent(message)}`
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
return () => {
|
||||
if ('receiveSignRequestFromAndroid' in window) {
|
||||
window.receiveSignRequestFromAndroid = undefined;
|
||||
}
|
||||
};
|
||||
}, [navigation, accounts, currentIndex, selectedNetwork]);
|
||||
|
||||
return null;
|
||||
};
|
@ -1,11 +1,20 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { createWallet } from "../utils/accounts";
|
||||
import { sendMessage } from "../utils/misc";
|
||||
import useAccountsData from "./useAccountsData";
|
||||
import { useNetworks } from "../context/NetworksContext";
|
||||
|
||||
const useGetOrCreateAccounts = () => {
|
||||
declare global {
|
||||
interface Window {
|
||||
Android?: {
|
||||
onSignatureComplete?: (signature: string) => void;
|
||||
onSignatureError?: (error: string) => void;
|
||||
onSignatureCancelled?: () => void;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const useGetOrCreateAccounts = (onWalletCreated?: () => void) => {
|
||||
const { networksData } = useNetworks();
|
||||
const { getAccountsData } = useAccountsData();
|
||||
|
||||
@ -21,6 +30,8 @@ const useGetOrCreateAccounts = () => {
|
||||
|
||||
// Re-fetch newly created accounts
|
||||
accountsData = await getAccountsData(event.data.chainId);
|
||||
|
||||
onWalletCreated?.();
|
||||
}
|
||||
|
||||
sendMessage(
|
||||
@ -30,12 +41,33 @@ const useGetOrCreateAccounts = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const autoCreateAccounts = async () => {
|
||||
const defaultChainId = networksData[0]?.chainId;
|
||||
if (!defaultChainId) return;
|
||||
|
||||
let accountsData = await getAccountsData(defaultChainId);
|
||||
|
||||
if (accountsData.length === 0) {
|
||||
console.log("Auto-creating wallet...");
|
||||
await createWallet(networksData);
|
||||
accountsData = await getAccountsData(defaultChainId);
|
||||
|
||||
onWalletCreated?.();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('message', handleCreateAccounts);
|
||||
|
||||
const isAndroidWebView = !!(window.Android);
|
||||
|
||||
if (isAndroidWebView) {
|
||||
autoCreateAccounts();
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('message', handleCreateAccounts);
|
||||
};
|
||||
}, [networksData, getAccountsData]);
|
||||
}, [networksData, getAccountsData, onWalletCreated]);
|
||||
};
|
||||
|
||||
export default useGetOrCreateAccounts;
|
||||
export default useGetOrCreateAccounts;
|
@ -18,6 +18,8 @@ import { useNetworks } from "../context/NetworksContext";
|
||||
import ImportWalletDialog from "../components/ImportWalletDialog";
|
||||
import { MnemonicDialog } from "../components/MnemonicDialog";
|
||||
import { Container } from "../components/Container";
|
||||
import { SignRequestHandler } from '../components/SignRequestHandler';
|
||||
import useGetOrCreateAccounts from '../hooks/useGetOrCreateAccounts';
|
||||
import { IS_IMPORT_WALLET_ENABLED } from "../utils/constants";
|
||||
|
||||
const HomeScreen = () => {
|
||||
@ -64,8 +66,34 @@ const HomeScreen = () => {
|
||||
setPhrase(mnemonic);
|
||||
setSelectedNetwork(networksData[0]);
|
||||
}
|
||||
setIsWalletCreating(false);
|
||||
};
|
||||
|
||||
const handleWalletCreated = useCallback(() => {
|
||||
setIsWalletCreated(true);
|
||||
fetchAccounts();
|
||||
}, [fetchAccounts]);
|
||||
|
||||
useGetOrCreateAccounts(handleWalletCreated);
|
||||
|
||||
useEffect(() => {
|
||||
fetchAccounts();
|
||||
}, [networksData, setAccounts, selectedNetwork, fetchAccounts]);
|
||||
|
||||
useEffect(() => {
|
||||
const initializeWallet = async () => {
|
||||
if (!isWalletCreated && networksData.length > 0) {
|
||||
const mnemonic = await createWallet(networksData);
|
||||
if (mnemonic) {
|
||||
await fetchAccounts();
|
||||
setSelectedNetwork(networksData[0]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
initializeWallet();
|
||||
}, [networksData, isWalletCreated, fetchAccounts, setSelectedNetwork]);
|
||||
|
||||
const importWalletHandler = async (recoveryPhrase: string) => {
|
||||
try {
|
||||
const mnemonic = await createWallet(networksData, recoveryPhrase);
|
||||
@ -114,10 +142,6 @@ const HomeScreen = () => {
|
||||
setCurrentIndex(0);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchAccounts();
|
||||
}, [networksData, setAccounts, selectedNetwork, fetchAccounts]);
|
||||
|
||||
return (
|
||||
<View style={styles.appContainer}>
|
||||
<Container>
|
||||
@ -161,6 +185,7 @@ const HomeScreen = () => {
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<SignRequestHandler />
|
||||
<ImportWalletDialog
|
||||
visible={importWalletDialog}
|
||||
hideDialog={() => setImportWalletDialog(false)}
|
||||
|
@ -10,6 +10,7 @@ export type StackParamsList = {
|
||||
selectedNamespace: string;
|
||||
selectedChainId: string;
|
||||
accountInfo: Account;
|
||||
prefillMessage?: string;
|
||||
};
|
||||
SignRequest: {
|
||||
namespace: string;
|
||||
|
Loading…
Reference in New Issue
Block a user