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 { useEffect } from "react";
|
||||||
|
|
||||||
import { createWallet } from "../utils/accounts";
|
import { createWallet } from "../utils/accounts";
|
||||||
import { sendMessage } from "../utils/misc";
|
import { sendMessage } from "../utils/misc";
|
||||||
import useAccountsData from "./useAccountsData";
|
import useAccountsData from "./useAccountsData";
|
||||||
import { useNetworks } from "../context/NetworksContext";
|
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 { networksData } = useNetworks();
|
||||||
const { getAccountsData } = useAccountsData();
|
const { getAccountsData } = useAccountsData();
|
||||||
|
|
||||||
@ -21,6 +30,8 @@ const useGetOrCreateAccounts = () => {
|
|||||||
|
|
||||||
// Re-fetch newly created accounts
|
// Re-fetch newly created accounts
|
||||||
accountsData = await getAccountsData(event.data.chainId);
|
accountsData = await getAccountsData(event.data.chainId);
|
||||||
|
|
||||||
|
onWalletCreated?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(
|
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);
|
window.addEventListener('message', handleCreateAccounts);
|
||||||
|
|
||||||
|
const isAndroidWebView = !!(window.Android);
|
||||||
|
|
||||||
|
if (isAndroidWebView) {
|
||||||
|
autoCreateAccounts();
|
||||||
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('message', handleCreateAccounts);
|
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 ImportWalletDialog from "../components/ImportWalletDialog";
|
||||||
import { MnemonicDialog } from "../components/MnemonicDialog";
|
import { MnemonicDialog } from "../components/MnemonicDialog";
|
||||||
import { Container } from "../components/Container";
|
import { Container } from "../components/Container";
|
||||||
|
import { SignRequestHandler } from '../components/SignRequestHandler';
|
||||||
|
import useGetOrCreateAccounts from '../hooks/useGetOrCreateAccounts';
|
||||||
import { IS_IMPORT_WALLET_ENABLED } from "../utils/constants";
|
import { IS_IMPORT_WALLET_ENABLED } from "../utils/constants";
|
||||||
|
|
||||||
const HomeScreen = () => {
|
const HomeScreen = () => {
|
||||||
@ -64,8 +66,34 @@ const HomeScreen = () => {
|
|||||||
setPhrase(mnemonic);
|
setPhrase(mnemonic);
|
||||||
setSelectedNetwork(networksData[0]);
|
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) => {
|
const importWalletHandler = async (recoveryPhrase: string) => {
|
||||||
try {
|
try {
|
||||||
const mnemonic = await createWallet(networksData, recoveryPhrase);
|
const mnemonic = await createWallet(networksData, recoveryPhrase);
|
||||||
@ -114,10 +142,6 @@ const HomeScreen = () => {
|
|||||||
setCurrentIndex(0);
|
setCurrentIndex(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchAccounts();
|
|
||||||
}, [networksData, setAccounts, selectedNetwork, fetchAccounts]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.appContainer}>
|
<View style={styles.appContainer}>
|
||||||
<Container>
|
<Container>
|
||||||
@ -161,6 +185,7 @@ const HomeScreen = () => {
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
<SignRequestHandler />
|
||||||
<ImportWalletDialog
|
<ImportWalletDialog
|
||||||
visible={importWalletDialog}
|
visible={importWalletDialog}
|
||||||
hideDialog={() => setImportWalletDialog(false)}
|
hideDialog={() => setImportWalletDialog(false)}
|
||||||
|
@ -10,6 +10,7 @@ export type StackParamsList = {
|
|||||||
selectedNamespace: string;
|
selectedNamespace: string;
|
||||||
selectedChainId: string;
|
selectedChainId: string;
|
||||||
accountInfo: Account;
|
accountInfo: Account;
|
||||||
|
prefillMessage?: string;
|
||||||
};
|
};
|
||||||
SignRequest: {
|
SignRequest: {
|
||||||
namespace: string;
|
namespace: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user