diff --git a/src/App.tsx b/src/App.tsx index fd8c034..6439bc0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -45,6 +45,7 @@ import SignRequestEmbed from "./screens/SignRequestEmbed"; import useAddAccountEmbed from "./hooks/useAddAccountEmbed"; import useExportPKEmbed from "./hooks/useExportPrivateKeyEmbed"; import { SignTxEmbed } from "./screens/SignTxEmbed"; +import useGetOrCreateNetwork from "./hooks/useGetOrNetworkAccounts"; const Stack = createStackNavigator(); @@ -287,6 +288,7 @@ const App = (): React.JSX.Element => { useWebViewHandler(); useAddAccountEmbed(); useExportPKEmbed(); + useGetOrCreateNetwork(); return ( diff --git a/src/hooks/useGetOrCreateAccounts.ts b/src/hooks/useGetOrCreateAccounts.ts index b203d55..62005c7 100644 --- a/src/hooks/useGetOrCreateAccounts.ts +++ b/src/hooks/useGetOrCreateAccounts.ts @@ -1,12 +1,11 @@ import { useEffect, useCallback } from "react"; -import { addNewNetwork, createWallet, isChainIdPresent } from "../utils/accounts"; +import { createWallet } from "../utils/accounts"; import { sendMessage } from "../utils/misc"; import useAccountsData from "./useAccountsData"; import { useNetworks } from "../context/NetworksContext"; import { useAccounts } from "../context/AccountsContext"; import { REQUEST_CREATE_OR_GET_ACCOUNTS, WALLET_ACCOUNTS_DATA } from "../utils/constants"; -import { NetworksFormData } from "../types"; const REACT_APP_ALLOWED_URLS = import.meta.env.REACT_APP_ALLOWED_URLS; @@ -16,24 +15,12 @@ const useGetOrCreateAccounts = () => { const { setAccounts } = useAccounts(); // Wrap the function in useCallback to prevent recreation on each render - const getOrCreateAccountsForChain = useCallback(async (chainId: string, networkData?: NetworksFormData) => { + const getOrCreateAccountsForChain = useCallback(async (chainId: string) => { let accountsData = await getAccountsData(chainId); if (accountsData.length === 0) { console.log("Accounts not found, creating wallet..."); await createWallet(networksData); - - const isNetworkPresent = await isChainIdPresent(chainId); - if (!isNetworkPresent) { - if (!networkData || chainId !== networkData.chainId) { - console.log('Network data not available.'); - return []; - } - - console.log('ChainId not found. Adding network') - await addNewNetwork(networkData); - } - accountsData = await getAccountsData(chainId); } diff --git a/src/hooks/useGetOrNetworkAccounts.ts b/src/hooks/useGetOrNetworkAccounts.ts new file mode 100644 index 0000000..5e37539 --- /dev/null +++ b/src/hooks/useGetOrNetworkAccounts.ts @@ -0,0 +1,105 @@ +import { useEffect, useCallback } from "react"; + +import { addNewNetwork, createWallet, isChainIdPresent, isWalletCreated } from "../utils/accounts"; +import { sendMessage } from "../utils/misc"; +import useAccountsData from "./useAccountsData"; +import { useNetworks } from "../context/NetworksContext"; +import { useAccounts } from "../context/AccountsContext"; +import { ADD_NETWORK, WALLET_ACCOUNTS_DATA } from "../utils/constants"; +import { NetworksFormData } from "../types"; + +const REACT_APP_ALLOWED_URLS = import.meta.env.REACT_APP_ALLOWED_URLS; + +const useGetOrCreateNetwork = () => { + const { networksData } = useNetworks(); + const { getAccountsData } = useAccountsData(); + const { setAccounts } = useAccounts(); + + const getOrCreateNetwork = useCallback(async (chainId: string, networkData?: NetworksFormData) => { + const isCreated = await isWalletCreated(); + + if (!isCreated) { + console.log("Wallet not found, creating wallet..."); + await createWallet(networksData); + } + + const isNetworkPresent = await isChainIdPresent(chainId); + if (!isNetworkPresent) { + if (!networkData || chainId !== networkData.chainId) { + console.log('Network data not available.'); + return []; + } + + console.log('ChainId not found. Adding network') + await addNewNetwork(networkData); + } + + const accountsData = await getAccountsData(chainId); + + // Update the AccountsContext with the new accounts + setAccounts(accountsData); + + return accountsData; + }, [networksData, getAccountsData, setAccounts]); + + useEffect(() => { + const handleCreateAccounts = async (event: MessageEvent) => { + if (event.data.type !== ADD_NETWORK) return; + + if (!REACT_APP_ALLOWED_URLS) { + console.log('Allowed URLs are not set'); + return; + } + + const allowedUrls = REACT_APP_ALLOWED_URLS.split(',').map(url => url.trim()); + + if (!allowedUrls.includes(event.origin)) { + console.log('Unauthorized app.'); + return; + } + + const { chainId, networkData } = event.data; + + const accountsData = await getOrCreateNetwork(chainId, networkData); + const accountsAddressList = accountsData.map(account => account.address); + console.log('Sending WALLET_ACCOUNTS_DATA accounts:', accountsAddressList); + + sendMessage( + event.source as Window, WALLET_ACCOUNTS_DATA, + accountsAddressList, + event.origin + ); + }; + + const autoCreateAccounts = async () => { + const defaultChainId = networksData[0]?.chainId; + + if (!defaultChainId) { + console.log('useGetOrCreateAccounts: No default chainId found'); + return; + } + const accounts = await getOrCreateNetwork(defaultChainId); + + // Only notify Android when we actually have accounts + if (accounts.length > 0 && window.Android?.onAccountsReady) { + window.Android.onAccountsReady(); + } else { + console.log('No accounts created or Android bridge not available'); + } + }; + + window.addEventListener('message', handleCreateAccounts); + + const isAndroidWebView = !!(window.Android); + + if (isAndroidWebView) { + autoCreateAccounts(); + } + + return () => { + window.removeEventListener('message', handleCreateAccounts); + }; + }, [networksData, getAccountsData, getOrCreateNetwork]); +}; + +export default useGetOrCreateNetwork; diff --git a/src/utils/accounts.ts b/src/utils/accounts.ts index 4760b16..b80016e 100644 --- a/src/utils/accounts.ts +++ b/src/utils/accounts.ts @@ -448,6 +448,14 @@ const isChainIdPresent = async ( return networksData.some((network) => network.chainId === chainId); } +const isWalletCreated = async ( +): Promise => { + const mnemonicServer = await getInternetCredentials("mnemonicServer"); + const mnemonic = mnemonicServer; + + return mnemonic !== null; +}; + export { createWallet, addAccount, @@ -463,5 +471,6 @@ export { updateAccountCounter, getCosmosAccountByHDPath, addNewNetwork, - isChainIdPresent + isChainIdPresent, + isWalletCreated };