From 8d60fd9e4baccbe3050eb0d332d2426e7f271b7d Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 5 Jun 2025 10:03:22 +0530 Subject: [PATCH 01/14] Create hook to add network --- src/App.tsx | 2 + src/hooks/useAddNetworkEmbed.ts | 39 +++++++++++++++++++ src/screens/AddNetwork.tsx | 68 ++------------------------------- src/utils/accounts.ts | 67 ++++++++++++++++++++++++++++++++ src/utils/constants.ts | 1 + 5 files changed, 113 insertions(+), 64 deletions(-) create mode 100644 src/hooks/useAddNetworkEmbed.ts diff --git a/src/App.tsx b/src/App.tsx index fd8c034..7392606 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 useAddNetworkEmbed from "./hooks/useAddNetworkEmbed"; const Stack = createStackNavigator(); @@ -287,6 +288,7 @@ const App = (): React.JSX.Element => { useWebViewHandler(); useAddAccountEmbed(); useExportPKEmbed(); + useAddNetworkEmbed(); return ( diff --git a/src/hooks/useAddNetworkEmbed.ts b/src/hooks/useAddNetworkEmbed.ts new file mode 100644 index 0000000..7ec6357 --- /dev/null +++ b/src/hooks/useAddNetworkEmbed.ts @@ -0,0 +1,39 @@ +import { useEffect } from 'react'; + +import { addNewNetwork } from '../utils/accounts'; +import { ADD_NETWORK } from '../utils/constants'; + +const REACT_APP_ALLOWED_URLS = import.meta.env.REACT_APP_ALLOWED_URLS; + +const useAddNetworkEmbed = () => { + useEffect(() => { + const handleAddNetwork = 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; + } + + try { + const { networkData } = event.data; + await addNewNetwork(networkData); + } catch (err) { + console.error('Error preparing sign request:', err); + } + }; + + window.addEventListener('message', handleAddNetwork); + return () => window.removeEventListener('message', handleAddNetwork); + }, []); + +} + +export default useAddNetworkEmbed; diff --git a/src/screens/AddNetwork.tsx b/src/screens/AddNetwork.tsx index 338ec3f..f662c77 100644 --- a/src/screens/AddNetwork.tsx +++ b/src/screens/AddNetwork.tsx @@ -1,8 +1,6 @@ import React, { useCallback, useEffect, useState } from "react"; import { useForm, Controller, useWatch, FieldErrors } from "react-hook-form"; import { TextInput, HelperText } from "react-native-paper"; - -import { HDNode } from "ethers/lib/utils"; import { chains } from "chain-registry"; import { useDebouncedCallback } from "use-debounce"; import { z } from "zod"; @@ -10,27 +8,21 @@ import { z } from "zod"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { useNavigation } from "@react-navigation/native"; import { zodResolver } from "@hookform/resolvers/zod"; +import { Divider, Grid } from "@mui/material"; +import { LoadingButton } from "@mui/lab"; import { StackParamsList } from "../types"; import { SelectNetworkType } from "../components/SelectNetworkType"; -import { addAccountsForNetwork, getNextAccountId, storeNetworkData } from "../utils/accounts"; +import { addAccountsForNetwork, addNewNetwork, getNextAccountId, storeNetworkData } from "../utils/accounts"; import { useNetworks } from "../context/NetworksContext"; import { - COSMOS, EIP155, CHAINID_DEBOUNCE_DELAY, EMPTY_FIELD_ERROR, INVALID_URL_ERROR, IS_NUMBER_REGEX, } from "../utils/constants"; -import { getCosmosAccountByHDPath } from "../utils/accounts"; import ETH_CHAINS from "../assets/ethereum-chains.json"; -import { - getInternetCredentials, - setInternetCredentials, -} from "../utils/key-store"; -import { Divider, Grid } from "@mui/material"; -import { LoadingButton } from "@mui/lab"; import { Layout } from "../components/Layout"; const ethNetworkDataSchema = z.object({ @@ -143,42 +135,8 @@ const AddNetwork = () => { isDefault: false, }; - const mnemonicServer = await getInternetCredentials("mnemonicServer"); - const mnemonic = mnemonicServer; + const retrievedNetworksData = await addNewNetwork(newNetworkData); - if (!mnemonic) { - throw new Error("Mnemonic not found"); - } - - const hdNode = HDNode.fromMnemonic(mnemonic); - - const hdPath = `m/44'/${newNetworkData.coinType}'/0'/0/0`; - const node = hdNode.derivePath(hdPath); - let address; - - switch (newNetworkData.namespace) { - case EIP155: - address = node.address; - break; - - case COSMOS: - address = ( - await getCosmosAccountByHDPath( - mnemonic, - hdPath, - (newNetworkData as z.infer) - .addressPrefix, - ) - ).data.address; - break; - - default: - throw new Error("Unsupported namespace"); - } - - const accountInfo = `${hdPath},${node.privateKey},${node.publicKey},${address}`; - - const retrievedNetworksData = await storeNetworkData(newNetworkData); setNetworksData(retrievedNetworksData); // Get number of accounts in first network @@ -190,24 +148,6 @@ const AddNetwork = () => { (network) => network.chainId === newNetworkData.chainId, ); - await Promise.all([ - setInternetCredentials( - `accounts/${newNetworkData.namespace}:${newNetworkData.chainId}/0`, - "_", - accountInfo, - ), - setInternetCredentials( - `addAccountCounter/${newNetworkData.namespace}:${newNetworkData.chainId}`, - "_", - "1", - ), - setInternetCredentials( - `accountIndices/${newNetworkData.namespace}:${newNetworkData.chainId}`, - "_", - "0", - ), - ]); - await addAccountsForNetwork(selectedNetwork!, nextAccountId - 1); navigation.navigate("Home"); diff --git a/src/utils/accounts.ts b/src/utils/accounts.ts index b65e63d..73f5a27 100644 --- a/src/utils/accounts.ts +++ b/src/utils/accounts.ts @@ -160,6 +160,66 @@ const addAccountFromHDPath = async ( } }; +const addNewNetwork = async ( + newNetworkData: NetworksFormData +): Promise => { + const mnemonicServer = await getInternetCredentials("mnemonicServer"); + const mnemonic = mnemonicServer; + + if (!mnemonic) { + throw new Error("Mnemonic not found"); + } + + const hdNode = HDNode.fromMnemonic(mnemonic); + + const hdPath = `m/44'/${newNetworkData.coinType}'/0'/0/0`; + const node = hdNode.derivePath(hdPath); + let address; + + switch (newNetworkData.namespace) { + case EIP155: + address = node.address; + break; + + case COSMOS: + address = ( + await getCosmosAccountByHDPath( + mnemonic, + hdPath, + newNetworkData.addressPrefix, + ) + ).data.address; + break; + + default: + throw new Error("Unsupported namespace"); + } + + const accountInfo = `${hdPath},${node.privateKey},${node.publicKey},${address}`; + + await Promise.all([ + setInternetCredentials( + `accounts/${newNetworkData.namespace}:${newNetworkData.chainId}/0`, + "_", + accountInfo, + ), + setInternetCredentials( + `addAccountCounter/${newNetworkData.namespace}:${newNetworkData.chainId}`, + "_", + "1", + ), + setInternetCredentials( + `accountIndices/${newNetworkData.namespace}:${newNetworkData.chainId}`, + "_", + "0", + ), + ]); + + const retrievedNetworksData = await storeNetworkData(newNetworkData); + + return retrievedNetworksData; +} + const storeNetworkData = async ( networkData: NetworksFormData, ): Promise => { @@ -180,11 +240,13 @@ const storeNetworkData = async ( networkId: String(networkId), }, ]; + await setInternetCredentials( 'networks', '_', JSON.stringify(updatedNetworks), ); + return updatedNetworks; }; @@ -194,7 +256,9 @@ const retrieveNetworksData = async (): Promise => { if(!networks){ return []; } + const parsedNetworks: NetworksDataState[] = JSON.parse(networks); + return parsedNetworks; }; @@ -217,6 +281,7 @@ export const retrieveAccountsForNetwork = async ( address, hdPath: path, }; + return account; }), ); @@ -234,6 +299,7 @@ const retrieveAccounts = async ( if (!accountIndices) { return; } + const loadedAccounts = await retrieveAccountsForNetwork( `${currentNetworkData.namespace}:${currentNetworkData.chainId}`, accountIndices, @@ -382,4 +448,5 @@ export { getNextAccountId, updateAccountCounter, getCosmosAccountByHDPath, + addNewNetwork }; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index a657f5a..bb1db15 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -98,6 +98,7 @@ export const REQUEST_ACCOUNT_PK = 'REQUEST_ACCOUNT_PK'; export const REQUEST_ADD_ACCOUNT = 'REQUEST_ADD_ACCOUNT'; export const AUTO_SIGN_IN = 'AUTO_SIGN_IN'; export const CHECK_BALANCE = 'CHECK_BALANCE'; +export const ADD_NETWORK = 'ADD_NETWORK'; // iframe response types export const COSMOS_ACCOUNTS_RESPONSE = 'COSMOS_ACCOUNTS_RESPONSE'; -- 2.45.2 From a0df2fd8530407af8f98e698c0d63489229021b5 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 5 Jun 2025 10:36:59 +0530 Subject: [PATCH 02/14] Add network if present after creating wallet --- src/App.tsx | 2 -- src/hooks/useAddNetworkEmbed.ts | 39 ----------------------------- src/hooks/useGetOrCreateAccounts.ts | 17 +++++++++++-- src/utils/accounts.ts | 17 ++++++++++++- 4 files changed, 31 insertions(+), 44 deletions(-) delete mode 100644 src/hooks/useAddNetworkEmbed.ts diff --git a/src/App.tsx b/src/App.tsx index 7392606..fd8c034 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -45,7 +45,6 @@ import SignRequestEmbed from "./screens/SignRequestEmbed"; import useAddAccountEmbed from "./hooks/useAddAccountEmbed"; import useExportPKEmbed from "./hooks/useExportPrivateKeyEmbed"; import { SignTxEmbed } from "./screens/SignTxEmbed"; -import useAddNetworkEmbed from "./hooks/useAddNetworkEmbed"; const Stack = createStackNavigator(); @@ -288,7 +287,6 @@ const App = (): React.JSX.Element => { useWebViewHandler(); useAddAccountEmbed(); useExportPKEmbed(); - useAddNetworkEmbed(); return ( diff --git a/src/hooks/useAddNetworkEmbed.ts b/src/hooks/useAddNetworkEmbed.ts deleted file mode 100644 index 7ec6357..0000000 --- a/src/hooks/useAddNetworkEmbed.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { useEffect } from 'react'; - -import { addNewNetwork } from '../utils/accounts'; -import { ADD_NETWORK } from '../utils/constants'; - -const REACT_APP_ALLOWED_URLS = import.meta.env.REACT_APP_ALLOWED_URLS; - -const useAddNetworkEmbed = () => { - useEffect(() => { - const handleAddNetwork = 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; - } - - try { - const { networkData } = event.data; - await addNewNetwork(networkData); - } catch (err) { - console.error('Error preparing sign request:', err); - } - }; - - window.addEventListener('message', handleAddNetwork); - return () => window.removeEventListener('message', handleAddNetwork); - }, []); - -} - -export default useAddNetworkEmbed; diff --git a/src/hooks/useGetOrCreateAccounts.ts b/src/hooks/useGetOrCreateAccounts.ts index 62005c7..b203d55 100644 --- a/src/hooks/useGetOrCreateAccounts.ts +++ b/src/hooks/useGetOrCreateAccounts.ts @@ -1,11 +1,12 @@ import { useEffect, useCallback } from "react"; -import { createWallet } from "../utils/accounts"; +import { addNewNetwork, createWallet, isChainIdPresent } 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; @@ -15,12 +16,24 @@ const useGetOrCreateAccounts = () => { const { setAccounts } = useAccounts(); // Wrap the function in useCallback to prevent recreation on each render - const getOrCreateAccountsForChain = useCallback(async (chainId: string) => { + const getOrCreateAccountsForChain = useCallback(async (chainId: string, networkData?: NetworksFormData) => { 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/utils/accounts.ts b/src/utils/accounts.ts index 73f5a27..4760b16 100644 --- a/src/utils/accounts.ts +++ b/src/utils/accounts.ts @@ -434,6 +434,20 @@ const getCosmosAccountByHDPath = async ( return { cosmosWallet, data }; }; +const isChainIdPresent = async ( + chainId: string, +): Promise => { + const networks = await getInternetCredentials('networks'); + + if(!networks){ + return false; + } + + const networksData: NetworksFormData[] = JSON.parse(networks); + + return networksData.some((network) => network.chainId === chainId); +} + export { createWallet, addAccount, @@ -448,5 +462,6 @@ export { getNextAccountId, updateAccountCounter, getCosmosAccountByHDPath, - addNewNetwork + addNewNetwork, + isChainIdPresent }; -- 2.45.2 From 1c8f0fbcfb8f58716374d785bd3689d60388826a Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 5 Jun 2025 11:21:54 +0530 Subject: [PATCH 03/14] Create separate hook for adding network and getting account --- src/App.tsx | 2 + src/hooks/useGetOrCreateAccounts.ts | 17 +---- src/hooks/useGetOrNetworkAccounts.ts | 105 +++++++++++++++++++++++++++ src/utils/accounts.ts | 11 ++- 4 files changed, 119 insertions(+), 16 deletions(-) create mode 100644 src/hooks/useGetOrNetworkAccounts.ts 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 }; -- 2.45.2 From 36bb645e65b43b842aa76b5d67018dc6826f5ab6 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 5 Jun 2025 12:48:42 +0530 Subject: [PATCH 04/14] Use networks data from local storage --- src/hooks/useGetOrNetworkAccounts.ts | 52 ++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/src/hooks/useGetOrNetworkAccounts.ts b/src/hooks/useGetOrNetworkAccounts.ts index 5e37539..89e0e5b 100644 --- a/src/hooks/useGetOrNetworkAccounts.ts +++ b/src/hooks/useGetOrNetworkAccounts.ts @@ -1,6 +1,6 @@ import { useEffect, useCallback } from "react"; -import { addNewNetwork, createWallet, isChainIdPresent, isWalletCreated } from "../utils/accounts"; +import { addNewNetwork, createWallet, isChainIdPresent, isWalletCreated, retrieveAccounts } from "../utils/accounts"; import { sendMessage } from "../utils/misc"; import useAccountsData from "./useAccountsData"; import { useNetworks } from "../context/NetworksContext"; @@ -11,9 +11,9 @@ 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 { networksData, setNetworksData } = useNetworks(); const { setAccounts } = useAccounts(); + const { getAccountsData } = useAccountsData(); const getOrCreateNetwork = useCallback(async (chainId: string, networkData?: NetworksFormData) => { const isCreated = await isWalletCreated(); @@ -24,23 +24,53 @@ const useGetOrCreateNetwork = () => { } const isNetworkPresent = await isChainIdPresent(chainId); + + let resolvedNetworkData: NetworksFormData | undefined = undefined; + if (!isNetworkPresent) { if (!networkData || chainId !== networkData.chainId) { - console.log('Network data not available.'); + console.log("Network data not available."); return []; } - console.log('ChainId not found. Adding network') - await addNewNetwork(networkData); + console.log("ChainId not found. Adding network"); + + resolvedNetworkData = { + chainId: networkData.chainId, + namespace: networkData.namespace, + networkName: networkData.networkName, + rpcUrl: networkData.rpcUrl, + blockExplorerUrl: networkData.blockExplorerUrl || "", + addressPrefix: networkData.addressPrefix || "", + coinType: networkData.coinType || "", + nativeDenom: networkData.nativeDenom || "", + gasPrice: networkData.gasPrice || String(import.meta.env.REACT_APP_DEFAULT_GAS_PRICE || ""), + currencySymbol: networkData.currencySymbol || "", + isDefault: false, + }; + + const retrievedNetworksData = await addNewNetwork(resolvedNetworkData); + setNetworksData(retrievedNetworksData); + } else { + // fallback if the network already exists, try to find it from networksData + resolvedNetworkData = networksData.find(net => net.chainId === chainId); } - const accountsData = await getAccountsData(chainId); + if (!resolvedNetworkData) { + console.warn("Resolved network data is not available"); + return []; + } - // Update the AccountsContext with the new accounts - setAccounts(accountsData); + const accounts = await retrieveAccounts({ ...resolvedNetworkData, networkId: '' }); - return accountsData; - }, [networksData, getAccountsData, setAccounts]); + if (!accounts) { + return []; + } + + setAccounts(accounts); + + return accounts; + }, [networksData, setAccounts, setNetworksData]); useEffect(() => { const handleCreateAccounts = async (event: MessageEvent) => { -- 2.45.2 From 08b44293ef56cde92c46658054a75db7af6460e5 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 5 Jun 2025 14:38:59 +0530 Subject: [PATCH 05/14] Refactor add network hook --- src/hooks/useGetOrNetworkAccounts.ts | 161 +++++++++++---------------- 1 file changed, 68 insertions(+), 93 deletions(-) diff --git a/src/hooks/useGetOrNetworkAccounts.ts b/src/hooks/useGetOrNetworkAccounts.ts index 89e0e5b..32730fe 100644 --- a/src/hooks/useGetOrNetworkAccounts.ts +++ b/src/hooks/useGetOrNetworkAccounts.ts @@ -1,135 +1,110 @@ import { useEffect, useCallback } from "react"; -import { addNewNetwork, createWallet, isChainIdPresent, isWalletCreated, retrieveAccounts } from "../utils/accounts"; -import { sendMessage } from "../utils/misc"; -import useAccountsData from "./useAccountsData"; +import { addNewNetwork, createWallet, isChainIdPresent, isWalletCreated } from "../utils/accounts"; import { useNetworks } from "../context/NetworksContext"; -import { useAccounts } from "../context/AccountsContext"; -import { ADD_NETWORK, WALLET_ACCOUNTS_DATA } from "../utils/constants"; +import { ADD_NETWORK } from "../utils/constants"; import { NetworksFormData } from "../types"; +import { sendMessage } from "../utils/misc"; const REACT_APP_ALLOWED_URLS = import.meta.env.REACT_APP_ALLOWED_URLS; const useGetOrCreateNetwork = () => { const { networksData, setNetworksData } = useNetworks(); - const { setAccounts } = useAccounts(); - const { getAccountsData } = useAccountsData(); - 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); - - let resolvedNetworkData: NetworksFormData | undefined = undefined; - - if (!isNetworkPresent) { - if (!networkData || chainId !== networkData.chainId) { - console.log("Network data not available."); - return []; + const getOrCreateNetwork = useCallback( + async (chainId: string, networkData?: NetworksFormData, sourceOrigin?: string) => { + if (!sourceOrigin) { + return; } - console.log("ChainId not found. Adding network"); + try { + const isCreated = await isWalletCreated(); - resolvedNetworkData = { - chainId: networkData.chainId, - namespace: networkData.namespace, - networkName: networkData.networkName, - rpcUrl: networkData.rpcUrl, - blockExplorerUrl: networkData.blockExplorerUrl || "", - addressPrefix: networkData.addressPrefix || "", - coinType: networkData.coinType || "", - nativeDenom: networkData.nativeDenom || "", - gasPrice: networkData.gasPrice || String(import.meta.env.REACT_APP_DEFAULT_GAS_PRICE || ""), - currencySymbol: networkData.currencySymbol || "", - isDefault: false, - }; + if (!isCreated) { + console.log("Wallet not found, creating wallet..."); + await createWallet(networksData); + } - const retrievedNetworksData = await addNewNetwork(resolvedNetworkData); - setNetworksData(retrievedNetworksData); - } else { - // fallback if the network already exists, try to find it from networksData - resolvedNetworkData = networksData.find(net => net.chainId === chainId); - } + const isNetworkPresent = await isChainIdPresent(chainId); - if (!resolvedNetworkData) { - console.warn("Resolved network data is not available"); - return []; - } + if (!isNetworkPresent) { + if (!networkData || chainId !== networkData.chainId) { + console.log("Network data not available."); + if (sourceOrigin) { + sendMessage(window.parent, "NETWORK_ADD_FAILED", { + type: "NETWORK_ADD_FAILED", + message: "Invalid or missing network data" + }, sourceOrigin); + } + return; + } - const accounts = await retrieveAccounts({ ...resolvedNetworkData, networkId: '' }); + console.log("ChainId not found. Adding network"); - if (!accounts) { - return []; - } + const resolvedNetworkData = { + chainId: networkData.chainId, + namespace: networkData.namespace, + networkName: networkData.networkName, + rpcUrl: networkData.rpcUrl, + blockExplorerUrl: networkData.blockExplorerUrl || "", + addressPrefix: networkData.addressPrefix || "", + coinType: networkData.coinType || "", + nativeDenom: networkData.nativeDenom || "", + gasPrice: networkData.gasPrice || String(import.meta.env.REACT_APP_DEFAULT_GAS_PRICE || ""), + currencySymbol: networkData.currencySymbol || "", + isDefault: false, + }; - setAccounts(accounts); + const retrievedNetworksData = await addNewNetwork(resolvedNetworkData); + setNetworksData(retrievedNetworksData); - return accounts; - }, [networksData, setAccounts, setNetworksData]); + sendMessage(window.parent, "NETWORK_ADDED_SUCCESSFULLY", { + type: "NETWORK_ADDED_SUCCESSFULLY", + chainId + }, sourceOrigin); + } else { + sendMessage(window.parent, "NETWORK_ALREADY_EXISTS", { + type: "NETWORK_ALREADY_EXISTS", + chainId + }, sourceOrigin); + } + } catch (error) { + console.error("Error in getOrCreateNetwork:", error); + sendMessage(window.parent, "NETWORK_ADD_FAILED", { + type: "NETWORK_ADD_FAILED", + message: error instanceof Error ? error.message : "Unknown error" + }, sourceOrigin); + } + }, + [networksData, setNetworksData] + ); 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'); + console.log("Allowed URLs are not set"); return; } - const allowedUrls = REACT_APP_ALLOWED_URLS.split(',').map(url => url.trim()); + const allowedUrls = REACT_APP_ALLOWED_URLS.split(",").map(url => url.trim()); if (!allowedUrls.includes(event.origin)) { - console.log('Unauthorized app.'); + 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 - ); + await getOrCreateNetwork(chainId, networkData, 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(); - } - + window.addEventListener("message", handleCreateAccounts); return () => { - window.removeEventListener('message', handleCreateAccounts); + window.removeEventListener("message", handleCreateAccounts); }; - }, [networksData, getAccountsData, getOrCreateNetwork]); + }, [getOrCreateNetwork]); }; export default useGetOrCreateNetwork; -- 2.45.2 From 7db4b150578d19ed35674eb38fb959cc347dd246 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 5 Jun 2025 14:43:40 +0530 Subject: [PATCH 06/14] Update message type --- src/hooks/useGetOrNetworkAccounts.ts | 8 ++++---- src/utils/constants.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hooks/useGetOrNetworkAccounts.ts b/src/hooks/useGetOrNetworkAccounts.ts index 32730fe..1ca563c 100644 --- a/src/hooks/useGetOrNetworkAccounts.ts +++ b/src/hooks/useGetOrNetworkAccounts.ts @@ -2,7 +2,7 @@ import { useEffect, useCallback } from "react"; import { addNewNetwork, createWallet, isChainIdPresent, isWalletCreated } from "../utils/accounts"; import { useNetworks } from "../context/NetworksContext"; -import { ADD_NETWORK } from "../utils/constants"; +import { REQUEST_ADD_NETWORK } from "../utils/constants"; import { NetworksFormData } from "../types"; import { sendMessage } from "../utils/misc"; @@ -12,7 +12,7 @@ const useGetOrCreateNetwork = () => { const { networksData, setNetworksData } = useNetworks(); const getOrCreateNetwork = useCallback( - async (chainId: string, networkData?: NetworksFormData, sourceOrigin?: string) => { + async (chainId: string, networkData: NetworksFormData, sourceOrigin?: string) => { if (!sourceOrigin) { return; } @@ -28,7 +28,7 @@ const useGetOrCreateNetwork = () => { const isNetworkPresent = await isChainIdPresent(chainId); if (!isNetworkPresent) { - if (!networkData || chainId !== networkData.chainId) { + if (chainId !== networkData.chainId) { console.log("Network data not available."); if (sourceOrigin) { sendMessage(window.parent, "NETWORK_ADD_FAILED", { @@ -81,7 +81,7 @@ const useGetOrCreateNetwork = () => { useEffect(() => { const handleCreateAccounts = async (event: MessageEvent) => { - if (event.data.type !== ADD_NETWORK) return; + if (event.data.type !== REQUEST_ADD_NETWORK) return; if (!REACT_APP_ALLOWED_URLS) { console.log("Allowed URLs are not set"); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index bb1db15..a1b65a5 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -98,7 +98,7 @@ export const REQUEST_ACCOUNT_PK = 'REQUEST_ACCOUNT_PK'; export const REQUEST_ADD_ACCOUNT = 'REQUEST_ADD_ACCOUNT'; export const AUTO_SIGN_IN = 'AUTO_SIGN_IN'; export const CHECK_BALANCE = 'CHECK_BALANCE'; -export const ADD_NETWORK = 'ADD_NETWORK'; +export const REQUEST_ADD_NETWORK = 'REQUEST_ADD_NETWORK'; // iframe response types export const COSMOS_ACCOUNTS_RESPONSE = 'COSMOS_ACCOUNTS_RESPONSE'; -- 2.45.2 From 96cb0a8051f6cd1efdbea7dc1eae8a78eec743e4 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 5 Jun 2025 15:29:40 +0530 Subject: [PATCH 07/14] Add accounts for newly added network --- src/hooks/useGetOrNetworkAccounts.ts | 13 ++++++++++++- src/screens/AddNetwork.tsx | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/hooks/useGetOrNetworkAccounts.ts b/src/hooks/useGetOrNetworkAccounts.ts index 1ca563c..21acebd 100644 --- a/src/hooks/useGetOrNetworkAccounts.ts +++ b/src/hooks/useGetOrNetworkAccounts.ts @@ -1,6 +1,6 @@ import { useEffect, useCallback } from "react"; -import { addNewNetwork, createWallet, isChainIdPresent, isWalletCreated } from "../utils/accounts"; +import { addAccountsForNetwork, addNewNetwork, createWallet, getNextAccountId, isChainIdPresent, isWalletCreated } from "../utils/accounts"; import { useNetworks } from "../context/NetworksContext"; import { REQUEST_ADD_NETWORK } from "../utils/constants"; import { NetworksFormData } from "../types"; @@ -58,6 +58,17 @@ const useGetOrCreateNetwork = () => { const retrievedNetworksData = await addNewNetwork(resolvedNetworkData); setNetworksData(retrievedNetworksData); + // Get number of accounts in first network + const nextAccountId = await getNextAccountId( + `${retrievedNetworksData[0].namespace}:${retrievedNetworksData[0].chainId}`, + ); + + const selectedNetwork = retrievedNetworksData.find( + (network) => network.chainId === chainId, + ); + + await addAccountsForNetwork(selectedNetwork!, nextAccountId - 1); + sendMessage(window.parent, "NETWORK_ADDED_SUCCESSFULLY", { type: "NETWORK_ADDED_SUCCESSFULLY", chainId diff --git a/src/screens/AddNetwork.tsx b/src/screens/AddNetwork.tsx index f662c77..e753ccf 100644 --- a/src/screens/AddNetwork.tsx +++ b/src/screens/AddNetwork.tsx @@ -13,7 +13,7 @@ import { LoadingButton } from "@mui/lab"; import { StackParamsList } from "../types"; import { SelectNetworkType } from "../components/SelectNetworkType"; -import { addAccountsForNetwork, addNewNetwork, getNextAccountId, storeNetworkData } from "../utils/accounts"; +import { addAccountsForNetwork, addNewNetwork, getNextAccountId } from "../utils/accounts"; import { useNetworks } from "../context/NetworksContext"; import { EIP155, -- 2.45.2 From 7e8d7e63e519af3dc2e45e46baec4c491ee8f184 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 5 Jun 2025 16:02:25 +0530 Subject: [PATCH 08/14] Use constants for event types --- src/App.tsx | 4 ++-- src/hooks/useGetOrNetworkAccounts.ts | 22 +++++++++++----------- src/utils/constants.ts | 3 +++ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 6439bc0..cf05ce5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -45,7 +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"; +import useCreateNetwork from "./hooks/useGetOrNetworkAccounts"; const Stack = createStackNavigator(); @@ -288,7 +288,7 @@ const App = (): React.JSX.Element => { useWebViewHandler(); useAddAccountEmbed(); useExportPKEmbed(); - useGetOrCreateNetwork(); + useCreateNetwork(); return ( diff --git a/src/hooks/useGetOrNetworkAccounts.ts b/src/hooks/useGetOrNetworkAccounts.ts index 21acebd..98d99cf 100644 --- a/src/hooks/useGetOrNetworkAccounts.ts +++ b/src/hooks/useGetOrNetworkAccounts.ts @@ -2,13 +2,13 @@ import { useEffect, useCallback } from "react"; import { addAccountsForNetwork, addNewNetwork, createWallet, getNextAccountId, isChainIdPresent, isWalletCreated } from "../utils/accounts"; import { useNetworks } from "../context/NetworksContext"; -import { REQUEST_ADD_NETWORK } from "../utils/constants"; +import { NETWORK_ADD_FAILED, NETWORK_ADDED_SUCCESSFULLY, NETWORK_ALREADY_EXISTS, REQUEST_ADD_NETWORK } from "../utils/constants"; import { NetworksFormData } from "../types"; import { sendMessage } from "../utils/misc"; const REACT_APP_ALLOWED_URLS = import.meta.env.REACT_APP_ALLOWED_URLS; -const useGetOrCreateNetwork = () => { +const useCreateNetwork = () => { const { networksData, setNetworksData } = useNetworks(); const getOrCreateNetwork = useCallback( @@ -31,8 +31,8 @@ const useGetOrCreateNetwork = () => { if (chainId !== networkData.chainId) { console.log("Network data not available."); if (sourceOrigin) { - sendMessage(window.parent, "NETWORK_ADD_FAILED", { - type: "NETWORK_ADD_FAILED", + sendMessage(window.parent, NETWORK_ADD_FAILED, { + type: NETWORK_ADD_FAILED, message: "Invalid or missing network data" }, sourceOrigin); } @@ -69,20 +69,20 @@ const useGetOrCreateNetwork = () => { await addAccountsForNetwork(selectedNetwork!, nextAccountId - 1); - sendMessage(window.parent, "NETWORK_ADDED_SUCCESSFULLY", { - type: "NETWORK_ADDED_SUCCESSFULLY", + sendMessage(window.parent, NETWORK_ADDED_SUCCESSFULLY, { + type: NETWORK_ADDED_SUCCESSFULLY, chainId }, sourceOrigin); } else { - sendMessage(window.parent, "NETWORK_ALREADY_EXISTS", { - type: "NETWORK_ALREADY_EXISTS", + sendMessage(window.parent, NETWORK_ALREADY_EXISTS, { + type: NETWORK_ALREADY_EXISTS, chainId }, sourceOrigin); } } catch (error) { console.error("Error in getOrCreateNetwork:", error); - sendMessage(window.parent, "NETWORK_ADD_FAILED", { - type: "NETWORK_ADD_FAILED", + sendMessage(window.parent, NETWORK_ADD_FAILED, { + type: NETWORK_ADD_FAILED, message: error instanceof Error ? error.message : "Unknown error" }, sourceOrigin); } @@ -118,4 +118,4 @@ const useGetOrCreateNetwork = () => { }, [getOrCreateNetwork]); }; -export default useGetOrCreateNetwork; +export default useCreateNetwork; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index a1b65a5..81745c3 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -99,6 +99,9 @@ export const REQUEST_ADD_ACCOUNT = 'REQUEST_ADD_ACCOUNT'; export const AUTO_SIGN_IN = 'AUTO_SIGN_IN'; export const CHECK_BALANCE = 'CHECK_BALANCE'; export const REQUEST_ADD_NETWORK = 'REQUEST_ADD_NETWORK'; +export const NETWORK_ADD_FAILED = "NETWORK_ADD_FAILED"; +export const NETWORK_ADDED_SUCCESSFULLY = "NETWORK_ADDED_SUCCESSFULLY"; +export const NETWORK_ALREADY_EXISTS = "NETWORK_ALREADY_EXISTS"; // iframe response types export const COSMOS_ACCOUNTS_RESPONSE = 'COSMOS_ACCOUNTS_RESPONSE'; -- 2.45.2 From be6ef373cb7a550ce133d5f913edd57538397421 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 5 Jun 2025 16:13:20 +0530 Subject: [PATCH 09/14] Update hook file name --- src/App.tsx | 2 +- src/hooks/{useGetOrNetworkAccounts.ts => useCreateNetwork.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/hooks/{useGetOrNetworkAccounts.ts => useCreateNetwork.ts} (100%) diff --git a/src/App.tsx b/src/App.tsx index cf05ce5..9cbe0bf 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -45,7 +45,7 @@ import SignRequestEmbed from "./screens/SignRequestEmbed"; import useAddAccountEmbed from "./hooks/useAddAccountEmbed"; import useExportPKEmbed from "./hooks/useExportPrivateKeyEmbed"; import { SignTxEmbed } from "./screens/SignTxEmbed"; -import useCreateNetwork from "./hooks/useGetOrNetworkAccounts"; +import useCreateNetwork from "./hooks/useCreateNetwork"; const Stack = createStackNavigator(); diff --git a/src/hooks/useGetOrNetworkAccounts.ts b/src/hooks/useCreateNetwork.ts similarity index 100% rename from src/hooks/useGetOrNetworkAccounts.ts rename to src/hooks/useCreateNetwork.ts -- 2.45.2 From 93e7207f147256d59d7ce180bd6a4511c9b4b87c Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 5 Jun 2025 16:54:24 +0530 Subject: [PATCH 10/14] Update constants file --- src/utils/constants.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 81745c3..9f3fbcc 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -99,9 +99,6 @@ export const REQUEST_ADD_ACCOUNT = 'REQUEST_ADD_ACCOUNT'; export const AUTO_SIGN_IN = 'AUTO_SIGN_IN'; export const CHECK_BALANCE = 'CHECK_BALANCE'; export const REQUEST_ADD_NETWORK = 'REQUEST_ADD_NETWORK'; -export const NETWORK_ADD_FAILED = "NETWORK_ADD_FAILED"; -export const NETWORK_ADDED_SUCCESSFULLY = "NETWORK_ADDED_SUCCESSFULLY"; -export const NETWORK_ALREADY_EXISTS = "NETWORK_ALREADY_EXISTS"; // iframe response types export const COSMOS_ACCOUNTS_RESPONSE = 'COSMOS_ACCOUNTS_RESPONSE'; @@ -113,3 +110,6 @@ export const ACCOUNT_PK_RESPONSE = 'ACCOUNT_PK_RESPONSE'; export const ADD_ACCOUNT_RESPONSE = 'ADD_ACCOUNT_RESPONSE'; export const WALLET_ACCOUNTS_DATA = 'WALLET_ACCOUNTS_DATA'; export const IS_SUFFICIENT = 'IS_SUFFICIENT'; +export const NETWORK_ADD_FAILED = "NETWORK_ADD_FAILED"; +export const NETWORK_ADDED_SUCCESSFULLY = "NETWORK_ADDED_SUCCESSFULLY"; +export const NETWORK_ALREADY_EXISTS = "NETWORK_ALREADY_EXISTS"; -- 2.45.2 From 54e75e1f3ac21a3720a57b3544c1f5a6bcacb37a Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Fri, 6 Jun 2025 09:28:06 +0530 Subject: [PATCH 11/14] Refactor method to add accounts for network --- src/hooks/useCreateNetwork.ts | 41 +++++++++++++---------------------- src/screens/AddNetwork.tsx | 13 +---------- src/utils/accounts.ts | 23 +++++++++++++++----- src/utils/constants.ts | 6 ++--- 4 files changed, 36 insertions(+), 47 deletions(-) diff --git a/src/hooks/useCreateNetwork.ts b/src/hooks/useCreateNetwork.ts index 98d99cf..64c61b9 100644 --- a/src/hooks/useCreateNetwork.ts +++ b/src/hooks/useCreateNetwork.ts @@ -1,8 +1,8 @@ import { useEffect, useCallback } from "react"; -import { addAccountsForNetwork, addNewNetwork, createWallet, getNextAccountId, isChainIdPresent, isWalletCreated } from "../utils/accounts"; +import { addNewNetwork, createWallet, checkNetworkForChainID, isWalletCreated } from "../utils/accounts"; import { useNetworks } from "../context/NetworksContext"; -import { NETWORK_ADD_FAILED, NETWORK_ADDED_SUCCESSFULLY, NETWORK_ALREADY_EXISTS, REQUEST_ADD_NETWORK } from "../utils/constants"; +import { NETWORK_ADDED_RESPONSE, NETWORK_ADD_FAILED_RESPONSE, NETWORK_ALREADY_EXISTS_RESPONSE, REQUEST_ADD_NETWORK } from "../utils/constants"; import { NetworksFormData } from "../types"; import { sendMessage } from "../utils/misc"; @@ -25,14 +25,14 @@ const useCreateNetwork = () => { await createWallet(networksData); } - const isNetworkPresent = await isChainIdPresent(chainId); + const isNetworkPresent = await checkNetworkForChainID(chainId); if (!isNetworkPresent) { if (chainId !== networkData.chainId) { console.log("Network data not available."); if (sourceOrigin) { - sendMessage(window.parent, NETWORK_ADD_FAILED, { - type: NETWORK_ADD_FAILED, + sendMessage(window.parent, NETWORK_ADD_FAILED_RESPONSE, { + type: NETWORK_ADD_FAILED_RESPONSE, message: "Invalid or missing network data" }, sourceOrigin); } @@ -50,7 +50,7 @@ const useCreateNetwork = () => { addressPrefix: networkData.addressPrefix || "", coinType: networkData.coinType || "", nativeDenom: networkData.nativeDenom || "", - gasPrice: networkData.gasPrice || String(import.meta.env.REACT_APP_DEFAULT_GAS_PRICE || ""), + gasPrice: networkData.gasPrice || String(import.meta.env.REACT_APP_DEFAULT_GAS_PRICE), currencySymbol: networkData.currencySymbol || "", isDefault: false, }; @@ -58,31 +58,20 @@ const useCreateNetwork = () => { const retrievedNetworksData = await addNewNetwork(resolvedNetworkData); setNetworksData(retrievedNetworksData); - // Get number of accounts in first network - const nextAccountId = await getNextAccountId( - `${retrievedNetworksData[0].namespace}:${retrievedNetworksData[0].chainId}`, - ); - - const selectedNetwork = retrievedNetworksData.find( - (network) => network.chainId === chainId, - ); - - await addAccountsForNetwork(selectedNetwork!, nextAccountId - 1); - - sendMessage(window.parent, NETWORK_ADDED_SUCCESSFULLY, { - type: NETWORK_ADDED_SUCCESSFULLY, + sendMessage(window.parent, NETWORK_ADDED_RESPONSE, { + type: NETWORK_ADDED_RESPONSE, chainId }, sourceOrigin); } else { - sendMessage(window.parent, NETWORK_ALREADY_EXISTS, { - type: NETWORK_ALREADY_EXISTS, + sendMessage(window.parent, NETWORK_ALREADY_EXISTS_RESPONSE, { + type: NETWORK_ALREADY_EXISTS_RESPONSE, chainId }, sourceOrigin); } } catch (error) { console.error("Error in getOrCreateNetwork:", error); - sendMessage(window.parent, NETWORK_ADD_FAILED, { - type: NETWORK_ADD_FAILED, + sendMessage(window.parent, NETWORK_ADD_FAILED_RESPONSE, { + type: NETWORK_ADD_FAILED_RESPONSE, message: error instanceof Error ? error.message : "Unknown error" }, sourceOrigin); } @@ -91,7 +80,7 @@ const useCreateNetwork = () => { ); useEffect(() => { - const handleCreateAccounts = async (event: MessageEvent) => { + const handleCreateNetwork = async (event: MessageEvent) => { if (event.data.type !== REQUEST_ADD_NETWORK) return; if (!REACT_APP_ALLOWED_URLS) { @@ -111,9 +100,9 @@ const useCreateNetwork = () => { await getOrCreateNetwork(chainId, networkData, event.origin); }; - window.addEventListener("message", handleCreateAccounts); + window.addEventListener("message", handleCreateNetwork); return () => { - window.removeEventListener("message", handleCreateAccounts); + window.removeEventListener("message", handleCreateNetwork); }; }, [getOrCreateNetwork]); }; diff --git a/src/screens/AddNetwork.tsx b/src/screens/AddNetwork.tsx index e753ccf..e2d9e71 100644 --- a/src/screens/AddNetwork.tsx +++ b/src/screens/AddNetwork.tsx @@ -13,7 +13,7 @@ import { LoadingButton } from "@mui/lab"; import { StackParamsList } from "../types"; import { SelectNetworkType } from "../components/SelectNetworkType"; -import { addAccountsForNetwork, addNewNetwork, getNextAccountId } from "../utils/accounts"; +import { addNewNetwork } from "../utils/accounts"; import { useNetworks } from "../context/NetworksContext"; import { EIP155, @@ -139,17 +139,6 @@ const AddNetwork = () => { setNetworksData(retrievedNetworksData); - // Get number of accounts in first network - const nextAccountId = await getNextAccountId( - `${retrievedNetworksData[0].namespace}:${retrievedNetworksData[0].chainId}`, - ); - - const selectedNetwork = retrievedNetworksData.find( - (network) => network.chainId === newNetworkData.chainId, - ); - - await addAccountsForNetwork(selectedNetwork!, nextAccountId - 1); - navigation.navigate("Home"); }, [navigation, namespace, setNetworksData], diff --git a/src/utils/accounts.ts b/src/utils/accounts.ts index b80016e..380922f 100644 --- a/src/utils/accounts.ts +++ b/src/utils/accounts.ts @@ -196,7 +196,7 @@ const addNewNetwork = async ( } const accountInfo = `${hdPath},${node.privateKey},${node.publicKey},${address}`; - + await Promise.all([ setInternetCredentials( `accounts/${newNetworkData.namespace}:${newNetworkData.chainId}/0`, @@ -214,9 +214,20 @@ const addNewNetwork = async ( "0", ), ]); - + const retrievedNetworksData = await storeNetworkData(newNetworkData); + // Get number of accounts in first network + const nextAccountId = await getNextAccountId( + `${retrievedNetworksData[0].namespace}:${retrievedNetworksData[0].chainId}`, + ); + + const selectedNetwork = retrievedNetworksData.find( + (network) => network.chainId === newNetworkData.chainId, + ); + + await addAccountsForNetwork(selectedNetwork!, nextAccountId - 1); + return retrievedNetworksData; } @@ -253,7 +264,7 @@ const storeNetworkData = async ( const retrieveNetworksData = async (): Promise => { const networks = await getInternetCredentials('networks'); - if(!networks){ + if (!networks) { return []; } @@ -434,12 +445,12 @@ const getCosmosAccountByHDPath = async ( return { cosmosWallet, data }; }; -const isChainIdPresent = async ( +const checkNetworkForChainID = async ( chainId: string, ): Promise => { const networks = await getInternetCredentials('networks'); - if(!networks){ + if (!networks) { return false; } @@ -471,6 +482,6 @@ export { updateAccountCounter, getCosmosAccountByHDPath, addNewNetwork, - isChainIdPresent, + checkNetworkForChainID, isWalletCreated }; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 9f3fbcc..85f888e 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -110,6 +110,6 @@ export const ACCOUNT_PK_RESPONSE = 'ACCOUNT_PK_RESPONSE'; export const ADD_ACCOUNT_RESPONSE = 'ADD_ACCOUNT_RESPONSE'; export const WALLET_ACCOUNTS_DATA = 'WALLET_ACCOUNTS_DATA'; export const IS_SUFFICIENT = 'IS_SUFFICIENT'; -export const NETWORK_ADD_FAILED = "NETWORK_ADD_FAILED"; -export const NETWORK_ADDED_SUCCESSFULLY = "NETWORK_ADDED_SUCCESSFULLY"; -export const NETWORK_ALREADY_EXISTS = "NETWORK_ALREADY_EXISTS"; +export const NETWORK_ADDED_RESPONSE = "NETWORK_ADDED_RESPONSE"; +export const NETWORK_ALREADY_EXISTS_RESPONSE = "NETWORK_ALREADY_EXISTS_RESPONSE"; +export const NETWORK_ADD_FAILED_RESPONSE = "NETWORK_ADD_FAILED_RESPONSE"; -- 2.45.2 From 6e82abd95583a0363075daba4dc89c10631dc34c Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Fri, 6 Jun 2025 11:00:08 +0530 Subject: [PATCH 12/14] Update network data type --- src/hooks/useCreateNetwork.ts | 2 +- src/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/useCreateNetwork.ts b/src/hooks/useCreateNetwork.ts index 64c61b9..39f387b 100644 --- a/src/hooks/useCreateNetwork.ts +++ b/src/hooks/useCreateNetwork.ts @@ -48,7 +48,7 @@ const useCreateNetwork = () => { rpcUrl: networkData.rpcUrl, blockExplorerUrl: networkData.blockExplorerUrl || "", addressPrefix: networkData.addressPrefix || "", - coinType: networkData.coinType || "", + coinType: networkData.coinType, nativeDenom: networkData.nativeDenom || "", gasPrice: networkData.gasPrice || String(import.meta.env.REACT_APP_DEFAULT_GAS_PRICE), currencySymbol: networkData.currencySymbol || "", diff --git a/src/types.ts b/src/types.ts index ae93310..f75f10b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -64,7 +64,7 @@ export type NetworksFormData = { namespace: string; nativeDenom?: string; addressPrefix?: string; - coinType?: string; + coinType: string; gasPrice?: string; isDefault: boolean; }; -- 2.45.2 From af63b9126ce8d8be98420594f8c6f8cef4abaf7e Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Fri, 6 Jun 2025 12:50:38 +0530 Subject: [PATCH 13/14] Fix chain ID --- .env.example | 2 -- src/hooks/useCreateNetwork.ts | 13 +----------- src/import-meta-env.d.ts | 1 - src/utils/constants.ts | 24 ---------------------- stack/stack-orchestrator/config/app/run.sh | 2 -- 5 files changed, 1 insertion(+), 41 deletions(-) diff --git a/.env.example b/.env.example index 7171052..2e44075 100644 --- a/.env.example +++ b/.env.example @@ -5,7 +5,5 @@ REACT_APP_DEFAULT_GAS_PRICE=0.025 REACT_APP_GAS_ADJUSTMENT=2 REACT_APP_LACONICD_RPC_URL=https://laconicd-sapo.laconic.com -REACT_APP_ZENITHD_RPC_URL= - # Example: https://example-url-1.com,https://example-url-2.com REACT_APP_ALLOWED_URLS= diff --git a/src/hooks/useCreateNetwork.ts b/src/hooks/useCreateNetwork.ts index 39f387b..e86a67e 100644 --- a/src/hooks/useCreateNetwork.ts +++ b/src/hooks/useCreateNetwork.ts @@ -28,21 +28,10 @@ const useCreateNetwork = () => { const isNetworkPresent = await checkNetworkForChainID(chainId); if (!isNetworkPresent) { - if (chainId !== networkData.chainId) { - console.log("Network data not available."); - if (sourceOrigin) { - sendMessage(window.parent, NETWORK_ADD_FAILED_RESPONSE, { - type: NETWORK_ADD_FAILED_RESPONSE, - message: "Invalid or missing network data" - }, sourceOrigin); - } - return; - } - console.log("ChainId not found. Adding network"); const resolvedNetworkData = { - chainId: networkData.chainId, + chainId, namespace: networkData.namespace, networkName: networkData.networkName, rpcUrl: networkData.rpcUrl, diff --git a/src/import-meta-env.d.ts b/src/import-meta-env.d.ts index 0a6dc72..388d2b7 100644 --- a/src/import-meta-env.d.ts +++ b/src/import-meta-env.d.ts @@ -5,7 +5,6 @@ interface ImportMetaEnv { readonly REACT_APP_DEFAULT_GAS_PRICE: string; readonly REACT_APP_GAS_ADJUSTMENT: string; readonly REACT_APP_LACONICD_RPC_URL: string; - readonly REACT_APP_ZENITHD_RPC_URL: string; readonly REACT_APP_ALLOWED_URLS: string; } diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 85f888e..3f93d29 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -18,30 +18,6 @@ export const DEFAULT_NETWORKS: NetworksFormData[] = [ gasPrice: '0.001', isDefault: true, }, - { - chainId: 'zenith-testnet-stage0', - networkName: 'zenithd stage 0 testnet', - namespace: COSMOS, - rpcUrl: import.meta.env.REACT_APP_ZENITHD_RPC_URL || '', - blockExplorerUrl: '', - nativeDenom: 'znt', - addressPrefix: 'zenith', - coinType: '118', - gasPrice: '0.01', - isDefault: true, - }, - { - chainId: 'zenith-testnet-stage1', - networkName: 'zenithd stage 1 testnet', - namespace: COSMOS, - rpcUrl: import.meta.env.REACT_APP_ZENITHD_RPC_URL || '', - blockExplorerUrl: '', - nativeDenom: 'znt', - addressPrefix: 'zenith', - coinType: '118', - gasPrice: '0.01', - isDefault: true, - }, { chainId: 'laconic_9000-1', networkName: 'laconicd', diff --git a/stack/stack-orchestrator/config/app/run.sh b/stack/stack-orchestrator/config/app/run.sh index be6b210..a9b2f31 100755 --- a/stack/stack-orchestrator/config/app/run.sh +++ b/stack/stack-orchestrator/config/app/run.sh @@ -10,7 +10,6 @@ echo "WALLET_CONNECT_ID: ${WALLET_CONNECT_ID}" echo "CERC_DEFAULT_GAS_PRICE: ${CERC_DEFAULT_GAS_PRICE}" echo "CERC_GAS_ADJUSTMENT: ${CERC_GAS_ADJUSTMENT}" echo "CERC_LACONICD_RPC_URL: ${CERC_LACONICD_RPC_URL}" -echo "CERC_ZENITHD_RPC_URL: ${CERC_ZENITHD_RPC_URL}" echo "CERC_ALLOWED_URLS: ${CERC_ALLOWED_URLS}" # Build with required env @@ -18,7 +17,6 @@ export REACT_APP_WALLET_CONNECT_PROJECT_ID=$WALLET_CONNECT_ID export REACT_APP_DEFAULT_GAS_PRICE=$CERC_DEFAULT_GAS_PRICE export REACT_APP_GAS_ADJUSTMENT=$CERC_GAS_ADJUSTMENT export REACT_APP_LACONICD_RPC_URL=$CERC_LACONICD_RPC_URL -export REACT_APP_ZENITHD_RPC_URL=$CERC_ZENITHD_RPC_URL export REACT_APP_ALLOWED_URLS=$CERC_ALLOWED_URLS # Set env variables in build -- 2.45.2 From 5a04bbe95f33adc38f47ec7fbf8a74310c4e06d8 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Fri, 6 Jun 2025 16:02:33 +0530 Subject: [PATCH 14/14] Update package version --- package.json | 2 +- src/hooks/useGetOrCreateAccounts.ts | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 862ee0a..1bd8843 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "web-wallet", - "version": "0.1.6", + "version": "0.1.7", "private": true, "dependencies": { "@cerc-io/registry-sdk": "^0.2.5", diff --git a/src/hooks/useGetOrCreateAccounts.ts b/src/hooks/useGetOrCreateAccounts.ts index 62005c7..ce6b950 100644 --- a/src/hooks/useGetOrCreateAccounts.ts +++ b/src/hooks/useGetOrCreateAccounts.ts @@ -1,6 +1,6 @@ import { useEffect, useCallback } from "react"; -import { createWallet } from "../utils/accounts"; +import { createWallet, isWalletCreated } from "../utils/accounts"; import { sendMessage } from "../utils/misc"; import useAccountsData from "./useAccountsData"; import { useNetworks } from "../context/NetworksContext"; @@ -16,14 +16,15 @@ const useGetOrCreateAccounts = () => { // Wrap the function in useCallback to prevent recreation on each render const getOrCreateAccountsForChain = useCallback(async (chainId: string) => { - let accountsData = await getAccountsData(chainId); + const isCreated = await isWalletCreated(); - if (accountsData.length === 0) { + if (!isCreated) { console.log("Accounts not found, creating wallet..."); await createWallet(networksData); - accountsData = await getAccountsData(chainId); } + const accountsData = await getAccountsData(chainId); + // Update the AccountsContext with the new accounts setAccounts(accountsData); -- 2.45.2