Create hook to add network

This commit is contained in:
IshaVenikar 2025-06-05 10:03:22 +05:30
parent fe3d2411a2
commit 8d60fd9e4b
5 changed files with 113 additions and 64 deletions

View File

@ -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<StackParamsList>();
@ -287,6 +288,7 @@ const App = (): React.JSX.Element => {
useWebViewHandler();
useAddAccountEmbed();
useExportPKEmbed();
useAddNetworkEmbed();
return (
<Surface style={styles.appSurface}>

View File

@ -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;

View File

@ -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<typeof cosmosNetworkDataSchema>)
.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");

View File

@ -160,6 +160,66 @@ const addAccountFromHDPath = async (
}
};
const addNewNetwork = async (
newNetworkData: NetworksFormData
): Promise<NetworksDataState[]> => {
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<NetworksDataState[]> => {
@ -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<NetworksDataState[]> => {
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
};

View File

@ -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';