Skip to content

Instantly share code, notes, and snippets.

@robksawyer
Last active July 14, 2021 16:07
Show Gist options
  • Save robksawyer/0af079e4a1b2a241cc648be9eb89df4e to your computer and use it in GitHub Desktop.
Save robksawyer/0af079e4a1b2a241cc648be9eb89df4e to your computer and use it in GitHub Desktop.
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import { providers, Signer, ethers } from "ethers";
import React, { useEffect, useState } from "react";
import Web3Modal, { IProviderOptions } from "web3modal";
const emptyContract = {
instance: undefined,
factory: undefined
};
const defaultProvider: providers.Provider | undefined = undefined;
export const ProviderContext = React.createContext<[providers.Provider | undefined, React.Dispatch<React.SetStateAction<providers.Provider | undefined>>]>([defaultProvider, () => { }]);
const defaultCurrentAddress: string = "";
export const CurrentAddressContext = React.createContext<[string, React.Dispatch<React.SetStateAction<string>>]>([defaultCurrentAddress, () => { }]);
const defaultSigner: Signer | undefined = undefined;
export const SignerContext = React.createContext<[Signer | undefined, React.Dispatch<React.SetStateAction<Signer | undefined>>]>([defaultSigner, () => { }]);
const defaultSymfoniContext: SymfoniContextInterface = {
currentHardhatProvider: "",
init: () => { throw Error("Symfoni context not initialized") },
loading: false,
messages: [],
providers: []
};
export const SymfoniContext = React.createContext<SymfoniContextInterface>(defaultSymfoniContext);
export interface SymfoniContextInterface {
init: (provider?: string) => void;
loading: boolean;
messages: string[];
currentHardhatProvider: string;
providers: string[];
}
export interface SymfoniProps {
autoInit?: boolean;
showLoading?: boolean;
loadingComponent?: React.ReactNode;
}
export const Symfoni: React.FC<SymfoniProps> = ({
showLoading = true,
autoInit = true,
...props
}) => {
const [initializeCounter, setInitializeCounter] = useState(0);
const [currentHardhatProvider, setCurrentHardhatProvider] = useState("");
const [loading, setLoading] = useState(false);
const [messages, setMessages] = useState<string[]>([]);
const [signer, setSigner] = useState<Signer | undefined>(defaultSigner);
const [provider, setProvider] = useState<providers.Provider | undefined>(defaultProvider);
const [currentAddress, setCurrentAddress] = useState<string>(defaultCurrentAddress);
const [fallbackProvider] = useState<string | undefined>(undefined);
const [providerPriority, setProviderPriority] = useState<string[]>(["web3modal", "hardhat"]);
useEffect(() => {
if (messages.length > 0)
console.debug(messages.pop())
}, [messages])
const getProvider = async (): Promise<{ provider: providers.Provider, hardhatProviderName: string } | undefined> => {
let hardhatProviderName = "Not set";
let _providerPriority = [...providerPriority];
// Fallback provider
if (fallbackProvider && autoInit && initializeCounter === 0) {
if (localStorage.getItem("WEB3_CONNECT_CACHED_PROVIDER") === null) {
_providerPriority = _providerPriority.sort((a, b) => {
return a === fallbackProvider ? -1 : b === fallbackProvider ? 1 : 0;
})
}
}
const provider = await _providerPriority.reduce(async (maybeProvider: Promise<providers.Provider | undefined>, providerIdentification) => {
let foundProvider = await maybeProvider
if (foundProvider) {
return Promise.resolve(foundProvider)
}
else {
switch (providerIdentification.toLowerCase()) {
case "web3modal":
try {
const provider = await getWeb3ModalProvider()
const web3provider = new ethers.providers.Web3Provider(provider);
hardhatProviderName = "web3modal";
return Promise.resolve(web3provider)
} catch (error) {
return Promise.resolve(undefined)
}
case "hardhat":
try {
const provider = new ethers.providers.JsonRpcProvider({
url: "http://127.0.0.1:8545",
});
hardhatProviderName = "hardhat";
return Promise.resolve(provider)
} catch (error) {
return Promise.resolve(undefined)
} default:
return Promise.resolve(undefined)
}
}
}, Promise.resolve(undefined)) // end reduce
return provider ? { provider, hardhatProviderName } : undefined
};
const getSigner = async (_provider: providers.Provider, hardhatProviderName: string): Promise<Signer | undefined> => {
switch (hardhatProviderName) {
case "web3modal":
const web3provider = _provider as ethers.providers.Web3Provider
return await web3provider.getSigner()
case "hardhat":
return ethers.Wallet.fromMnemonic("test test test test test test test test test test test junk").connect(_provider)
default:
return undefined
}
};
const getWeb3ModalProvider = async (): Promise<any> => {
const providerOptions: IProviderOptions = {
};
const web3Modal = new Web3Modal({
// network: "mainnet",
cacheProvider: false,
providerOptions, // required
});
return await web3Modal.connect();
};
useEffect(() => {
let subscribed = true
const doAsync = async () => {
const finish = (text: string) => {
setLoading(false)
setMessages(old => [...old, text])
}
const finishWithContracts = (text: string) => {
finish(text)
}
if (!autoInit && initializeCounter === 0) return finish("Auto init turned off.")
setLoading(true)
setMessages(old => [...old, "Initiating Symfoni React"])
const providerObject = await getProvider() // getProvider can actually return undefined, see issue https://github.com/microsoft/TypeScript/issues/11094
if (!subscribed || !providerObject) return finish("No provider or signer.")
const _provider = providerObject.provider
setProvider(_provider)
setMessages(old => [...old, "Useing " + providerObject.hardhatProviderName])
setCurrentHardhatProvider(providerObject.hardhatProviderName)
const _signer = await getSigner(_provider, providerObject.hardhatProviderName);
if (!subscribed || !_signer) return finishWithContracts("Provider, without signer.")
setSigner(_signer)
setMessages(old => [...old, "Useing signer"])
const address = await _signer.getAddress()
if (!subscribed || !address) return finishWithContracts("Provider and signer, without address.")
setCurrentAddress(address)
return finishWithContracts("Completed Symfoni context initialization.")
};
doAsync();
return () => { subscribed = false }
}, [initializeCounter])
const handleInitProvider = (provider?: string) => {
if (provider) {
setProviderPriority(old => old.sort((a, b) => {
return a === provider ? -1 : b === provider ? 1 : 0;
}))
}
setInitializeCounter(initializeCounter + 1)
}
return (
<SymfoniContext.Provider value={{ init: (provider) => handleInitProvider(provider), providers: providerPriority, currentHardhatProvider, loading, messages }}>
<ProviderContext.Provider value={[provider, setProvider]}>
<SignerContext.Provider value={[signer, setSigner]}>
<CurrentAddressContext.Provider value={[currentAddress, setCurrentAddress]}>
{showLoading && loading ?
props.loadingComponent
? props.loadingComponent
: <div>
{messages.map((msg, i) => (
<p key={i}>{msg}</p>
))}
</div>
: props.children
}
</CurrentAddressContext.Provider>
</SignerContext.Provider>
</ProviderContext.Provider>
</SymfoniContext.Provider>
)
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment