Waiting for WalletConnectV2
stable release and want ot see this library in Rust
- fix errors that are not handled
react-ethers
was created to facilitate the use, in React, of Ethers.js which is a library for interacting with Ethereum Blockchain. It aims to be a small dependence which can be easily used in any React dApp.
yarn add react-ethers
Use it with zero config:
// src/index.js
import { EVMContext } from "react-ethers"
ReactDOM.render(
<React.StrictMode>
<EVMContext>
<App />
</EVMContext>
</React.StrictMode>,
document.getElementById("root")
)
See how to add a config
(still using React17 for the moment)
// src/Dapp.js
import { useEVM } from "react-ethers"
const Dapp = () => {
const { network, account, provider, methods, connectionType } = useEVM()
return <>...</>
}
Available informations & methods:
// --- provider ---
type Provider = null | Web3Provider | FallbackProvider | BaseProvider
// --- network ---
type Network = {
name: string
chainId: number
blockHeight: number
publicEndpoints: string[]
explorerUrl: string
}
// --- account ---
interface Account {
isLogged: boolean
address: string
balance: string | number
walletType: string
signer: JsonRpcSigner
}
// --- methods ---
type Methods = {
launchConnection: (connectionType: ConnectionType) => void
setAutoRefresh: (setTo: boolean) => void
switchNetwork: (chainId: number) => void
loginToInjected: () => void
createVoidSigner: (address: string) => void
deleteVoidSigner: () => void
getNetworkList: () => Network[]
}
// --- connection type ---
type ConnectionType = "not initialized" | "injected" | "endpoints"
// --- others ---
autoRefreshActive: boolean
haveWebExtension: boolean
EthersJS References:
Web3Provider
FallbackProvider
JsonRpcSigner
There two type of connections:
-
injected
: using the web extensions to connect the blockchain (so through INFURA in the case of the basic configuration of Metamask for exemple). The provider is connected by default on the chosen network in the web extension, if this network is not known byEVMContext
this will set the name of the network asNetwork null (chainID:0)
.
You can usehaveWebExtension
to check if the user have an extension installed (window.ethereum
injected).
Caution: this is mainly tested with Metamask -
endpoints
: using one or several endpoints to connect the blockchain. It use aFallbackProvider
(witch use a quorum of provider). By default the network is set toEthereum Rinkeby testnet (chainID:4)
.
Useful for users who don't have a web extension and want to read blockchain informations.
import { useEVM } from "react-ethers"
const Dapp = () => {
const { methods } = useEVM()
{...}
return <>
<button onClick={() => methods.launchConnection("injected")}>
Launch connection with web extension
</button>
<button onClick={() => methods.launchConnection("endpoints")}>
Launch connection with endpoints
</button>
</>
}
To avoid any conflicts it is better to reload the page if you want to change the connectionType
You can config the default connection type by passing the defaultConnectionType
to the EVMContext
:
// src/index.js
import { EVMContext } from "react-ethers"
ReactDOM.render(
<React.StrictMode>
<EVMContext defaultConnectionType="endpoints" chainId={1}>
<App />
</EVMContext>
</React.StrictMode>,
document.getElementById("root")
)
Only on injected
connectionType
import { useEVM } from "react-ethers"
const Dapp = () => {
const { methods, account } = useEVM()
{...}
return <>
<button onClick={() => methods.loginToInjected()}>
Connect Metamask
</button>
{account.isLogged ? (
<p>Connected with {account.address}</p>
<p>Wallet type: {account.walletType}</p>
<p>Balance: {account.balance}</p>
<button onClick={() => console.log(account.signer)}>
Log signer
</button>
) : (
<p>Not connected</p>
)}
</>
}
Once connected you can access informations from account
.
There is no methods to disconnected the wallet, users have to do it directly on the wallet.
autoRefreshActive
is set by default to true
, it listen block on the provider and update the state (update balance if account is connected for exemple). You can disable by default in the EVMContext
config:
// src/index.js
import { EVMContext } from "react-ethers"
ReactDOM.render(
<React.StrictMode>
<EVMContext autoRefresh={false}>
<App />
</EVMContext>
</React.StrictMode>,
document.getElementById("root")
)
Or by using methods.setAutoRefresh
:
import { useEVM } from "react-ethers"
const Dapp = () => {
const { methods, autoRefreshActive } = useEVM()
{...}
return <>
<button
disabled={autoRefreshActive}
onClick={() => methods.setAutoRefresh(true)}
>
On
</button>
<button
disabled={!autoRefreshActive}
onClick={() => methods.setAutoRefresh(false)}
>
Off
</button>
</>
}
import { useEVM } from "react-ethers"
const Dapp = () => {
const { methods } = useEVM()
{...}
return <>
<button onClick={() => methods.switchNetwork(1)}>
Switch to Mainnet
</button>
</>
}
When the connection is injected
this will open the wallet (for Metamask) to confirm the switch of the network. All networks registered (on https://chainlist.org/ for exemple) in your web extensions are supported.
With endpoints
the page is reloaded on the chosen network. The network should be specified in react-ethers
or in the EVMContext
configuration:
// src/index.js
import { EVMContext } from "react-ethers"
ReactDOM.render(
<React.StrictMode>
<EVMContext
customNetworks={[
{
name: "Aurora Mainnet",
chainId: 1313161554,
blockHeight: 0,
publicEndpoints: ["https://mainnet.aurora.dev"],
explorerUrl: "https://aurorascan.dev/",
},
{
name: "Aurora Testnet",
chainId: 1313161555,
blockHeight: 0,
publicEndpoints: ["https://testnet.aurora.dev"],
explorerUrl: "https://testnet.aurorascan.dev/",
},
]}
>
<App />
</EVMContext>
</React.StrictMode>,
document.getElementById("root")
)
You can provide a list of endpoints in publicEndpoints
A void signer is a "watch-only" account that cannot sign transaction:
import { useEVM } from "react-ethers"
const Dapp = () => {
const { methods } = useEVM()
{...}
return <>
<button onClick={() => methods.createVoidSigner(
"0xe5cc7a18b29a090c4Cc72eC7270C4ee1498F73aF"
)}>
Use "watch-only" account
</button>
<button onClick={() => methods.deleteVoidSigner()}>
Delete void signer
</button>
</>
}
To create it you should not have any account connected to the dApp (in injected
connection) and not have any others void signer created.
import { useContract } from "react-ethers"
import contracts from "./contracts.json"
const Dapp = () => {
const { ropsten } = contracts
const token = useContract(
ropsten.FungibleToken.address,
ropsten.FungibleToken.abi
)
async function read() {
let supply
try {
supply = await token.totalSupply(anyAddress)
} catch (e) {
console.log(e)
}
console.log(supply)
}
return (
<>
<button onClick={read}>Log Total Supply</button>
</>
)
}
To avoid create multiple instance of your contract, consider using useContract
hook in a context or a single component.
In your .env
file you can add several API keys, which INFURA
is mandatory if you want to use Wallet Connect, and which can be useful for the performance of your app in read-only.
REACT_APP_INFURA_ID=""
REACT_APP_ALCHEMY_ID=""
REACT_APP_ETHERSCAN_ID=""
REACT_APP_POCKET_ID=""
You can contribute by:
- using the librairy and report bug
- share new ideas to improve it
- fork and pull request
©Raphaël