feat: sets up passing of custom RPCs to EthereumProvider

This commit is contained in:
Ben Kremer 2022-02-15 11:52:30 +01:00
parent 3e53d08874
commit 35868ea7af
2 changed files with 41 additions and 37 deletions

View File

@ -8,13 +8,7 @@ import Column from "./components/Column";
import Header from "./components/Header"; import Header from "./components/Header";
import Modal from "./components/Modal"; import Modal from "./components/Modal";
import { DEFAULT_MAIN_CHAINS, DEFAULT_TEST_CHAINS } from "./constants"; import { DEFAULT_MAIN_CHAINS, DEFAULT_TEST_CHAINS } from "./constants";
import { import { AccountAction, getLocalStorageTestnetFlag, setLocaleStorageTestnetFlag } from "./helpers";
getAllChainNamespaces,
AccountAction,
ChainNamespaces,
getLocalStorageTestnetFlag,
setLocaleStorageTestnetFlag,
} from "./helpers";
import Toggle from "./components/Toggle"; import Toggle from "./components/Toggle";
import RequestModal from "./modals/RequestModal"; import RequestModal from "./modals/RequestModal";
import PairingModal from "./modals/PairingModal"; import PairingModal from "./modals/PairingModal";
@ -30,7 +24,6 @@ import {
SToggleContainer, SToggleContainer,
} from "./components/app"; } from "./components/app";
import { useWalletConnectClient } from "./contexts/ClientContext"; import { useWalletConnectClient } from "./contexts/ClientContext";
import { apiGetChainNamespace, ChainsMap } from "caip-api";
import { utils } from "ethers"; import { utils } from "ethers";
interface IFormattedRpcResponse { interface IFormattedRpcResponse {
@ -42,7 +35,6 @@ interface IFormattedRpcResponse {
export default function App() { export default function App() {
const [isTestnet, setIsTestnet] = useState(getLocalStorageTestnetFlag()); const [isTestnet, setIsTestnet] = useState(getLocalStorageTestnetFlag());
const [chainData, setChainData] = useState<ChainNamespaces>({});
const [isRpcRequestPending, setIsRpcRequestPending] = useState(false); const [isRpcRequestPending, setIsRpcRequestPending] = useState(false);
const [rpcResult, setRpcResult] = useState<IFormattedRpcResponse | null>(); const [rpcResult, setRpcResult] = useState<IFormattedRpcResponse | null>();
@ -61,6 +53,7 @@ export default function App() {
chain, chain,
accounts, accounts,
balances, balances,
chainData,
isFetchingBalances, isFetchingBalances,
isInitializing, isInitializing,
onEnable, onEnable,
@ -74,29 +67,6 @@ export default function App() {
} }
}, [session, modal]); }, [session, modal]);
useEffect(() => {
loadChainData();
}, []);
const loadChainData = async () => {
const namespaces = getAllChainNamespaces();
const chainData: ChainNamespaces = {};
await Promise.all(
namespaces.map(async namespace => {
let chains: ChainsMap | undefined;
try {
chains = await apiGetChainNamespace(namespace);
} catch (e) {
// ignore error
}
if (typeof chains !== "undefined") {
chainData[namespace] = chains;
}
}),
);
setChainData(chainData);
};
// TODO: // TODO:
// const onPing = async () => { // const onPing = async () => {
// openPingModal(); // openPingModal();

View File

@ -1,4 +1,5 @@
import Client, { CLIENT_EVENTS } from "@walletconnect/client"; import Client, { CLIENT_EVENTS } from "@walletconnect/client";
import EthereumProvider from "@walletconnect/ethereum-provider";
import { PairingTypes, SessionTypes } from "@walletconnect/types"; import { PairingTypes, SessionTypes } from "@walletconnect/types";
import QRCodeModal from "@walletconnect/legacy-modal"; import QRCodeModal from "@walletconnect/legacy-modal";
import { import {
@ -16,9 +17,9 @@ import {
DEFAULT_PROJECT_ID, DEFAULT_PROJECT_ID,
DEFAULT_RELAY_URL, DEFAULT_RELAY_URL,
} from "../constants"; } from "../constants";
import { ERROR } from "@walletconnect/utils";
import EthereumProvider from "@walletconnect/ethereum-provider";
import { providers, utils } from "ethers"; import { providers, utils } from "ethers";
import { ChainNamespaces, getAllChainNamespaces } from "../helpers";
import { apiGetChainNamespace, ChainsMap } from "caip-api";
/** /**
* Types * Types
@ -33,7 +34,7 @@ interface IContext {
accounts: string[]; accounts: string[];
balances: { symbol: string; balance: string }[]; balances: { symbol: string; balance: string }[];
isFetchingBalances: boolean; isFetchingBalances: boolean;
setChain: (chainId: string) => void; chainData: ChainNamespaces;
onEnable: (chainId: string) => Promise<void>; onEnable: (chainId: string) => Promise<void>;
web3Provider?: providers.Web3Provider; web3Provider?: providers.Web3Provider;
} }
@ -60,6 +61,7 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
const [balances, setBalances] = useState<{ symbol: string; balance: string }[]>([]); const [balances, setBalances] = useState<{ symbol: string; balance: string }[]>([]);
const [accounts, setAccounts] = useState<string[]>([]); const [accounts, setAccounts] = useState<string[]>([]);
const [chainData, setChainData] = useState<ChainNamespaces>({});
const [chain, setChain] = useState<string>(""); const [chain, setChain] = useState<string>("");
const resetApp = () => { const resetApp = () => {
@ -70,6 +72,25 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
setChain(""); setChain("");
}; };
const loadChainData = async () => {
const namespaces = getAllChainNamespaces();
const chainData: ChainNamespaces = {};
await Promise.all(
namespaces.map(async namespace => {
let chains: ChainsMap | undefined;
try {
chains = await apiGetChainNamespace(namespace);
} catch (e) {
// ignore error
}
if (typeof chains !== "undefined") {
chainData[namespace] = chains;
}
}),
);
setChainData(chainData);
};
const disconnect = useCallback(async () => { const disconnect = useCallback(async () => {
if (typeof ethereumProvider === "undefined") { if (typeof ethereumProvider === "undefined") {
throw new Error("ethereumProvider is not initialized"); throw new Error("ethereumProvider is not initialized");
@ -129,11 +150,20 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
console.log("Enabling EthereumProvider for chainId: ", chainId); console.log("Enabling EthereumProvider for chainId: ", chainId);
const customRpcs = Object.keys(chainData.eip155).reduce(
(rpcs: Record<string, string>, chainId) => {
rpcs[chainId] = chainData.eip155[chainId].rpc[0];
return rpcs;
},
{},
);
// Create WalletConnect Provider // Create WalletConnect Provider
const ethereumProvider = new EthereumProvider({ const ethereumProvider = new EthereumProvider({
chainId: Number(chainId), chainId: Number(chainId),
rpc: { rpc: {
infuraId: DEFAULT_INFURA_ID, infuraId: DEFAULT_INFURA_ID,
custom: customRpcs,
}, },
// FIXME: `signer-connection` sub-dep is already specifying beta.23 -> typings mismatch. // FIXME: `signer-connection` sub-dep is already specifying beta.23 -> typings mismatch.
// @ts-ignore // @ts-ignore
@ -192,6 +222,10 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
[session, onEnable], [session, onEnable],
); );
useEffect(() => {
loadChainData();
}, []);
useEffect(() => { useEffect(() => {
if (!client) { if (!client) {
createClient(); createClient();
@ -220,7 +254,7 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
client, client,
session, session,
disconnect, disconnect,
setChain, chainData,
onEnable, onEnable,
web3Provider, web3Provider,
}), }),
@ -234,7 +268,7 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
client, client,
session, session,
disconnect, disconnect,
setChain, chainData,
onEnable, onEnable,
web3Provider, web3Provider,
], ],