refactor(dapp-v2): separates chainData into own context/hook

This commit is contained in:
Ben Kremer 2022-03-17 16:56:54 +01:00
parent 6b14e13eaf
commit 59b9eb5867
4 changed files with 87 additions and 43 deletions

View File

@ -30,6 +30,7 @@ import {
} from "./components/app";
import { useWalletConnectClient } from "./contexts/ClientContext";
import { useJsonRpc } from "./contexts/JsonRpcContext";
import { useChainData } from "./contexts/ChainDataContext";
export default function App() {
const [modal, setModal] = useState("");
@ -55,7 +56,6 @@ export default function App() {
// Use `JsonRpcContext` to provide us with relevant RPC methods and states.
const {
chainData,
ping,
ethereumRpc,
cosmosRpc,
@ -66,6 +66,8 @@ export default function App() {
setIsTestnet,
} = useJsonRpc();
const { chainData } = useChainData();
// Close the pairing modal after a session is established.
useEffect(() => {
if (session && modal === "pairing") {

View File

@ -0,0 +1,70 @@
import { apiGetChainNamespace, ChainsMap } from "caip-api";
import { createContext, ReactNode, useContext, useEffect, useState } from "react";
import { SolanaChainData } from "../chains/solana";
import { ChainNamespaces, getAllChainNamespaces } from "../helpers";
/**
* Types
*/
interface IContext {
chainData: ChainNamespaces;
}
/**
* Context
*/
export const ChainDataContext = createContext<IContext>({} as IContext);
/**
* Provider
*/
export function ChainDataContextProvider({ children }: { children: ReactNode | ReactNode[] }) {
const [chainData, setChainData] = useState<ChainNamespaces>({});
const loadChainData = async () => {
const namespaces = getAllChainNamespaces();
const chainData: ChainNamespaces = {};
await Promise.all(
namespaces.map(async namespace => {
let chains: ChainsMap | undefined;
try {
if (namespace === "solana") {
chains = SolanaChainData;
} else {
chains = await apiGetChainNamespace(namespace);
}
} catch (e) {
// ignore error
}
if (typeof chains !== "undefined") {
chainData[namespace] = chains;
}
}),
);
setChainData(chainData);
};
useEffect(() => {
loadChainData();
}, []);
return (
<ChainDataContext.Provider
value={{
chainData,
}}
>
{children}
</ChainDataContext.Provider>
);
}
export function useChainData() {
const context = useContext(ChainDataContext);
if (context === undefined) {
throw new Error("useChainData must be used within a ChainDataContextProvider");
}
return context;
}

View File

@ -1,29 +1,26 @@
import { BigNumber, utils } from "ethers";
import { createContext, ReactNode, useContext, useEffect, useState } from "react";
import { createContext, ReactNode, useContext, useState } from "react";
import * as encoding from "@walletconnect/encoding";
import { TypedDataField } from "@ethersproject/abstract-signer";
import { formatDirectSignDoc, stringifySignDocValues } from "cosmos-wallet";
import bs58 from "bs58";
import { verifyMessageSignature } from "solana-wallet";
import { clusterApiUrl, Connection, Keypair, SystemProgram, Transaction } from "@solana/web3.js";
import {
ChainNamespaces,
eip712,
formatTestTransaction,
getAllChainNamespaces,
getLocalStorageTestnetFlag,
hashPersonalMessage,
verifySignature,
} from "../helpers";
import { useWalletConnectClient } from "./ClientContext";
import { apiGetChainNamespace, ChainsMap } from "caip-api";
import { TypedDataField } from "@ethersproject/abstract-signer";
import {
DEFAULT_COSMOS_METHODS,
DEFAULT_EIP155_METHODS,
DEFAULT_SOLANA_METHODS,
} from "../constants";
import { clusterApiUrl, Connection, Keypair, SystemProgram, Transaction } from "@solana/web3.js";
import { SolanaChainData } from "../chains/solana";
import { useChainData } from "./ChainDataContext";
/**
* Types
@ -59,7 +56,6 @@ interface IContext {
testSignMessage: TRpcRequestCallback;
testSignTransaction: TRpcRequestCallback;
};
chainData: ChainNamespaces;
rpcResult?: IRpcResult | null;
isRpcRequestPending: boolean;
isTestnet: boolean;
@ -77,38 +73,11 @@ export const JsonRpcContext = createContext<IContext>({} as IContext);
export function JsonRpcContextProvider({ children }: { children: ReactNode | ReactNode[] }) {
const [pending, setPending] = useState(false);
const [result, setResult] = useState<IRpcResult | null>();
const [chainData, setChainData] = useState<ChainNamespaces>({});
const [isTestnet, setIsTestnet] = useState(getLocalStorageTestnetFlag());
const { client, session, accounts, balances, solanaPublicKeys } = useWalletConnectClient();
useEffect(() => {
loadChainData();
}, []);
const loadChainData = async () => {
const namespaces = getAllChainNamespaces();
const chainData: ChainNamespaces = {};
await Promise.all(
namespaces.map(async namespace => {
let chains: ChainsMap | undefined;
try {
if (namespace === "solana") {
chains = SolanaChainData;
} else {
chains = await apiGetChainNamespace(namespace);
}
} catch (e) {
// ignore error
}
if (typeof chains !== "undefined") {
chainData[namespace] = chains;
}
}),
);
setChainData(chainData);
};
const { chainData } = useChainData();
const _createJsonRpcRequestHandler =
(rpcRequest: (chainId: string, address: string) => Promise<IFormattedRpcResponse>) =>
@ -568,7 +537,6 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
return (
<JsonRpcContext.Provider
value={{
chainData,
ping,
ethereumRpc,
cosmosRpc,

View File

@ -1,8 +1,10 @@
import * as React from "react";
import * as ReactDOM from "react-dom";
import { createGlobalStyle } from "styled-components";
import { ClientContextProvider } from "./contexts/ClientContext";
import { JsonRpcContextProvider } from "./contexts/JsonRpcContext";
import { ChainDataContextProvider } from "./contexts/ChainDataContext";
import App from "./App";
import { globalStyle } from "./styles";
@ -20,11 +22,13 @@ declare global {
ReactDOM.render(
<>
<GlobalStyle />
<ClientContextProvider>
<JsonRpcContextProvider>
<App />
</JsonRpcContextProvider>
</ClientContextProvider>
<ChainDataContextProvider>
<ClientContextProvider>
<JsonRpcContextProvider>
<App />
</JsonRpcContextProvider>
</ClientContextProvider>
</ChainDataContextProvider>
</>,
document.getElementById("root"),
);