Refactor common code to custom hooks
This commit is contained in:
parent
f738311d4a
commit
cbbeaf4634
@ -1,6 +1,8 @@
|
||||
REACT_APP_WALLET_CONNECT_PROJECT_ID=
|
||||
|
||||
REACT_APP_DEFAULT_GAS_PRICE=0.025
|
||||
# Reference: https://github.com/cosmos/cosmos-sdk/issues/16020
|
||||
REACT_APP_GAS_ADJUSTMENT=2
|
||||
REACT_APP_LACONICD_RPC_URL=https://laconicd-sapo.laconic.com
|
||||
REACT_APP_AUTH_SECRET=
|
||||
|
||||
REACT_APP_DEPLOY_APP_URL=
|
||||
|
29
src/App.tsx
29
src/App.tsx
@ -24,7 +24,7 @@ import SignRequest from "./screens/SignRequest";
|
||||
import AddSession from "./screens/AddSession";
|
||||
import WalletConnect from "./screens/WalletConnect";
|
||||
import ApproveTransaction from "./screens/ApproveTransaction";
|
||||
import { Account, StackParamsList } from "./types";
|
||||
import { StackParamsList } from "./types";
|
||||
import { EIP155_SIGNING_METHODS } from "./utils/wallet-connect/EIP155Data";
|
||||
import { getSignParamsMessage } from "./utils/wallet-connect/helpers";
|
||||
import ApproveTransfer from "./screens/ApproveTransfer";
|
||||
@ -39,7 +39,7 @@ import { Header } from "./components/Header";
|
||||
import { WalletEmbed } from "./screens/WalletEmbed";
|
||||
import { AutoSignIn } from "./screens/AutoSignIn";
|
||||
import { checkSufficientFunds, getPathKey, sendMessage } from "./utils/misc";
|
||||
import { retrieveAccounts } from "./utils/accounts";
|
||||
import useAccountsData from "./hooks/useAccountsData";
|
||||
|
||||
const Stack = createStackNavigator<StackParamsList>();
|
||||
|
||||
@ -49,29 +49,14 @@ const App = (): React.JSX.Element => {
|
||||
const { web3wallet, setActiveSessions } = useWalletConnect();
|
||||
const { accounts, setCurrentIndex } = useAccounts();
|
||||
const { networksData, selectedNetwork, setSelectedNetwork } = useNetworks();
|
||||
const { getAccountsData } = useAccountsData(networksData);
|
||||
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [toastVisible, setToastVisible] = useState(false);
|
||||
const [currentProposal, setCurrentProposal] = useState<
|
||||
SignClientTypes.EventArguments["session_proposal"] | undefined
|
||||
>();
|
||||
|
||||
const getAccountsData = useCallback(async (chainId: string): Promise<Account[]> => {
|
||||
const targetNetwork = networksData.find(network => network.chainId === chainId);
|
||||
|
||||
if (!targetNetwork) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const accounts = await retrieveAccounts(targetNetwork);
|
||||
|
||||
if (!accounts || accounts.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return accounts
|
||||
}, [networksData]);
|
||||
|
||||
|
||||
const onSessionProposal = useCallback(
|
||||
async (proposal: SignClientTypes.EventArguments["session_proposal"]) => {
|
||||
if (!accounts.length || !accounts.length) {
|
||||
@ -254,7 +239,11 @@ const App = (): React.JSX.Element => {
|
||||
|
||||
const account = (await getAccountsData(chainId))[0];
|
||||
if (!account) {
|
||||
throw new Error('Account not found for the requested address.');
|
||||
throw new Error('Account not found');
|
||||
}
|
||||
|
||||
if (network.namespace !== COSMOS) {
|
||||
throw new Error('Unsupported network');
|
||||
}
|
||||
|
||||
const cosmosPrivKey = (
|
||||
|
20
src/hooks/useAccountsData.ts
Normal file
20
src/hooks/useAccountsData.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { useCallback } from "react";
|
||||
import { retrieveAccounts } from "../utils/accounts";
|
||||
import { NetworksDataState } from "../types";
|
||||
|
||||
const useAccountsData = (networksData: NetworksDataState[]) => {
|
||||
const getAccountsData = useCallback(async (chainId: string) => {
|
||||
const targetNetwork = networksData.find(network => network.chainId === chainId);
|
||||
|
||||
if (!targetNetwork) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const accounts = await retrieveAccounts(targetNetwork);
|
||||
return accounts || [];
|
||||
}, [networksData]);
|
||||
|
||||
return { getAccountsData };
|
||||
};
|
||||
|
||||
export default useAccountsData;
|
32
src/hooks/useGetOrCreateAccounts.ts
Normal file
32
src/hooks/useGetOrCreateAccounts.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { useEffect } from "react";
|
||||
import { createWallet } from "../utils/accounts";
|
||||
import { Account, NetworksDataState } from "../types";
|
||||
import { sendMessage } from "../utils/misc";
|
||||
|
||||
const useGetOrCreateAccounts = (networksData: NetworksDataState[], getAccountsData: (chainId: string) => Promise<Account[]>) => {
|
||||
useEffect(() => {
|
||||
const handleCreateAccounts = async (event: MessageEvent) => {
|
||||
if (event.data.type !== 'REQUEST_CREATE_OR_GET_ACCOUNTS') return;
|
||||
|
||||
let accountsData = await getAccountsData(event.data.chainId);
|
||||
|
||||
if (accountsData.length === 0) {
|
||||
console.log("Accounts not found, creating wallet...");
|
||||
await createWallet(networksData);
|
||||
|
||||
// Re-fetch newly created accounts
|
||||
accountsData = await getAccountsData(event.data.chainId);
|
||||
}
|
||||
|
||||
sendMessage(event.source as Window, 'WALLET_ACCOUNTS_DATA', accountsData, event.origin);
|
||||
};
|
||||
|
||||
window.addEventListener('message', handleCreateAccounts);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('message', handleCreateAccounts);
|
||||
};
|
||||
}, [networksData, getAccountsData ]);
|
||||
};
|
||||
|
||||
export default useGetOrCreateAccounts;
|
@ -1,35 +1,26 @@
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import { createWallet, retrieveAccounts } from '../utils/accounts';
|
||||
import { useNetworks } from '../context/NetworksContext';
|
||||
import { Account } from '../types';
|
||||
import { signMessage } from '../utils/sign-message';
|
||||
import { EIP155 } from '../utils/constants';
|
||||
import { sendMessage } from '../utils/misc';
|
||||
import useAccountsData from '../hooks/useAccountsData';
|
||||
import useGetOrCreateAccounts from '../hooks/useGetOrCreateAccounts';
|
||||
|
||||
export const AutoSignIn = () => {
|
||||
const { networksData } = useNetworks();
|
||||
|
||||
const getAccountsData = useCallback(async (chainId: string): Promise<Account[]> => {
|
||||
const targetNetwork = networksData.find(network => network.chainId === chainId);
|
||||
|
||||
if (!targetNetwork) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const accounts = await retrieveAccounts(targetNetwork);
|
||||
|
||||
if (!accounts || accounts.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return accounts
|
||||
}, [networksData]);
|
||||
const { getAccountsData } = useAccountsData(networksData);
|
||||
|
||||
useEffect(() => {
|
||||
const handleSignIn = async (event: MessageEvent) => {
|
||||
if (event.data.type !== 'AUTO_SIGN_IN') return;
|
||||
|
||||
if (event.origin !== process.env.REACT_APP_DEPLOY_APP_URL) {
|
||||
console.log('Unauthorized app.');
|
||||
return;
|
||||
}
|
||||
|
||||
const accountsData = await getAccountsData(event.data.chainId);
|
||||
|
||||
if (!accountsData.length) {
|
||||
@ -48,38 +39,8 @@ export const AutoSignIn = () => {
|
||||
};
|
||||
}, [networksData, getAccountsData]);
|
||||
|
||||
useEffect(() => {
|
||||
const getAccountAddress = async (event: MessageEvent) => {
|
||||
if (event.data.type !== 'GET_ACCOUNT_ADDRESS') return;
|
||||
|
||||
if (event.data.secret !== process.env.REACT_APP_AUTH_SECRET) {
|
||||
console.log('Unauthorized app.');
|
||||
return;
|
||||
}
|
||||
|
||||
let accountsData = await getAccountsData(event.data.chainId);
|
||||
|
||||
if (accountsData.length === 0) {
|
||||
console.log("Accounts not found, creating wallet...");
|
||||
await createWallet(networksData);
|
||||
|
||||
// Re-fetch newly created accounts
|
||||
accountsData = await getAccountsData(event.data.chainId);
|
||||
}
|
||||
|
||||
if (!accountsData.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendMessage(event.source as Window, 'ACCOUNT_ADDRESS_RESPONSE', accountsData[0].address, event.origin);
|
||||
};
|
||||
|
||||
window.addEventListener('message', getAccountAddress);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('message', getAccountAddress);
|
||||
};
|
||||
}, [networksData, getAccountsData]);
|
||||
// Custom hook for adding listener to get accounts data
|
||||
useGetOrCreateAccounts(networksData, getAccountsData)
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
SigningStargateClient,
|
||||
} from '@cosmjs/stargate';
|
||||
|
||||
import { createWallet, retrieveAccounts, retrieveSingleAccount } from '../utils/accounts';
|
||||
import { retrieveAccounts, retrieveSingleAccount } from '../utils/accounts';
|
||||
import AccountDetails from '../components/AccountDetails';
|
||||
import styles from '../styles/stylesheet';
|
||||
import DataBox from '../components/DataBox';
|
||||
@ -24,6 +24,7 @@ import { useNetworks } from '../context/NetworksContext';
|
||||
import TxErrorDialog from '../components/TxErrorDialog';
|
||||
import { MEMO } from '../screens/ApproveTransfer';
|
||||
import { Account, NetworksDataState } from '../types';
|
||||
import useGetOrCreateAccounts from '../hooks/useGetOrCreateAccounts';
|
||||
|
||||
type TransactionDetails = {
|
||||
chainId: string;
|
||||
@ -46,7 +47,7 @@ export const WalletEmbed = () => {
|
||||
|
||||
const { networksData } = useNetworks();
|
||||
|
||||
const getAccountsData = useCallback(async (chainId: string): Promise<string[]> => {
|
||||
const getAccountsData = useCallback(async (chainId: string): Promise<Account[]> => {
|
||||
const targetNetwork = networksData.find(network => network.chainId === chainId);
|
||||
|
||||
if (!targetNetwork) {
|
||||
@ -59,7 +60,7 @@ export const WalletEmbed = () => {
|
||||
return [];
|
||||
}
|
||||
|
||||
return accounts.map(account => account.address);
|
||||
return accounts;
|
||||
}, [networksData]);
|
||||
|
||||
useEffect(() => {
|
||||
@ -83,29 +84,8 @@ export const WalletEmbed = () => {
|
||||
};
|
||||
}, [getAccountsData]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleCreateAccounts = async (event: MessageEvent) => {
|
||||
if (event.data.type !== 'REQUEST_CREATE_OR_GET_ACCOUNTS') return;
|
||||
|
||||
let accountsData = await getAccountsData(event.data.chainId);
|
||||
|
||||
if (accountsData.length === 0) {
|
||||
console.log("Accounts not found, creating wallet...");
|
||||
await createWallet(networksData);
|
||||
|
||||
// Re-fetch newly created accounts
|
||||
accountsData = await getAccountsData(event.data.chainId);
|
||||
}
|
||||
|
||||
sendMessage(event.source as Window, 'WALLET_ACCOUNTS_DATA', accountsData, event.origin);
|
||||
};
|
||||
|
||||
window.addEventListener('message', handleCreateAccounts);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('message', handleCreateAccounts);
|
||||
};
|
||||
}, [networksData, getAccountsData]);
|
||||
// Custom hook for adding listener to get accounts data
|
||||
useGetOrCreateAccounts(networksData, getAccountsData);
|
||||
|
||||
const handleTxRequested = useCallback(
|
||||
async (event: MessageEvent) => {
|
||||
@ -168,7 +148,7 @@ export const WalletEmbed = () => {
|
||||
});
|
||||
|
||||
if (!checkSufficientFunds(amount, balance.amount)) {
|
||||
console.log("Insufficient funds detected");
|
||||
console.log("Insufficient funds detected. Throwing error.");
|
||||
throw new Error('Insufficient funds');
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ services:
|
||||
CERC_DEFAULT_GAS_PRICE: ${CERC_DEFAULT_GAS_PRICE:-0.025}
|
||||
CERC_GAS_ADJUSTMENT: ${CERC_GAS_ADJUSTMENT:-2}
|
||||
CERC_LACONICD_RPC_URL: ${CERC_LACONICD_RPC_URL:-https://laconicd.laconic.com}
|
||||
CERC_AUTH_SECRET: ${CERC_AUTH_SECRET}
|
||||
CERC_DEPLOY_APP_URL: ${CERC_DEPLOY_APP_URL}
|
||||
command: ["bash", "/scripts/run.sh"]
|
||||
volumes:
|
||||
- ../config/app/run.sh:/scripts/run.sh
|
||||
|
@ -10,14 +10,14 @@ 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_AUTH_SECRET: ${CERC_AUTH_SECRET}"
|
||||
echo "CERC_DEPLOY_APP_URL: ${CERC_DEPLOY_APP_URL}"
|
||||
|
||||
# Build with required env
|
||||
REACT_APP_WALLET_CONNECT_PROJECT_ID=$WALLET_CONNECT_ID \
|
||||
REACT_APP_DEFAULT_GAS_PRICE=$CERC_DEFAULT_GAS_PRICE \
|
||||
REACT_APP_GAS_ADJUSTMENT=$CERC_GAS_ADJUSTMENT \
|
||||
REACT_APP_LACONICD_RPC_URL=$CERC_LACONICD_RPC_URL \
|
||||
REACT_APP_AUTH_SECRET=$CERC_AUTH_SECRET \
|
||||
REACT_APP_DEPLOY_APP_URL=$CERC_DEPLOY_APP_URL \
|
||||
yarn build
|
||||
|
||||
# Define the directory and file path
|
||||
|
@ -64,8 +64,8 @@ Instructions for running the `laconic-wallet-web` using [laconic-so](https://git
|
||||
# RPC endpoint of laconicd node (default: https://laconicd.laconic.com)
|
||||
CERC_LACONICD_RPC_URL=
|
||||
|
||||
# Secret to protect auto sign-in route (should match the secret set in deploy app)
|
||||
REACT_APP_AUTH_SECRET=
|
||||
# Deploy app URL used for checking origin of the messages for auto-sign-in route
|
||||
REACT_APP_DEPLOY_APP_URL=
|
||||
```
|
||||
|
||||
## Start the deployment
|
||||
|
Loading…
Reference in New Issue
Block a user