or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Do you want to remove this version name and description?
Syncing
xxxxxxxxxx
How to Use Web3React in Your Next Project
By Gerhard Steenkamp and William Schwab
Here at Linum Labs we've built up a good amount of experience integrating wallets into apps. The go-to interface for doing this is almost certainly Pedro Gomes's web3modal, which is an excellent resource. We've been working a lot with another interface we hear mentioned less often - Uniswap's Noah Zinmeister's
web3react
library. There are a lot of touches in it that we really enjoy. There isn't much written about how to use it, though. We wrote some internal docs, and then realized that it would be great to share with the larger ecosystem.If you are from the
web3react
repo, we'd love to contribute our docs however suits you best. Please get in touch!Table of Contents
connector
account
activate
active
chainId
deactivate
error
provider
setError
Initial Setup
The first thing you'll need to do is install the
web3react
packages. You'll always need thecore
package, and will also need theweb3react
connectors for any wallets you plan on integrating. We'll talk about the wallet connectors separately here. For core, if you're using Yarn, you'd use:In order to make use of
web3react
inside your React app, you'll need to do a few things inside theApp
component:Web3ReactProvider
from@web3-react/core
Web3ReactProvider
componentgetLibrary
functionYour
App
component might look something like this:(This example is loosely based on the
web3react
docs.) The code above assumes that you're using Ethers.js (specifically theWeb3Provider
from Ethers), but the same can be done in web3.js. The idea is that you need to import a provider (generally via Ethers or Web3.js in the JavaScript/TypeScript space), and then instantiate and return it in thegetLibrary
function.Wallet and Provider Connectors
Wallets and web3 providers (such as Infura) connect to an app in
web3react
via aconnector
. If you wish to add a new wallet or provider, there is likely already a web3react package to aid the process. There is a list of packages on the landing page of the GitHub repo (here).Connecting Wallets
We'll describe the process of connecting a wallet using
web3-react
, and also use MetaMask and Portis as examples with code snippets.First you'll need to get the connector for the desired wallet from the
web3-react
repo. You can find the code for the connectors here, though each is also its own npm package, and should be added to your project using Yarn or NPM, installing each separately as needed.If we wanted MetaMask, we would get the package using
yarn add @web3-react/injected-connector
. (Theinjected-connector
isn't specific to MetaMask - any wallet which works by injecting itself into the browser (like Brave) will also use this package.) For Portis, it would beyarn add @web3react/portis-connector
.Each wallet needs its own unique instantiation details. We won't give a guide for each wallet here other than giving our WalletConnect example. If you want to add something else, head over to the package details in the
web3-react
repo and see what you'll need there.We'll start with the Portis example since most other wallets follow the same pattern. We'd head over to the
portis-connector
directory. In thesrc/
directory there we can see anindex.ts
file, which has a TypeScript interface calledPortisConstructorArguments
. These are the arguments you'll need when creating a Portis connector inside your app:MetaMask (and other injected wallets) work a bit differently than most of the other connectors, as its only argument is an array called
supportedchainIds
, which, as its name implies, is a list ofchainId
numbers the dapp should support.We'll need this information in a minute.
To connect MetaMask in your app, import the injected connector:
For Portis:
This is something you'll want to have run when your app instantiates (most likely), and you'd like it to be available anywhere in your app that interacts with the blockchain. As a result, in a global state store or high up in the tree make sense.
As mentioned before, the only argument is an array of
supportedChainId
s. If we're testing on Goerli, this means all we'd need to add is:(
chainId 5
is the Goerli testnet, you can replace that with whatever chain you want to work with or add several if your app is deployed on more than one network.)Portis has more arguments. For one, you'll need to set up a dApp ID at Portis. The optional config argument is specified in their docs; it allows you to set a number of options, and is worth checking out if you're building with Portis.
network
works identically tosupportedChainIds
in the injected connector - it's an array ofchainId
numbers to be supported.Next, if you are instantiating the connector in one place, but need access to the wallet in another, import your wallet wherever you need it like this:
Connecting with the Wallet
In order to connect with the wallet we've added, you'll need to form a
handleConnect
function, which takes a connector as an argument. We'll give an example of how you might want a funciton like this to look.We'll assume you're using web3.js, and that you have a connection to Infura, Alchemy, or a similar provider in order to instantiate a provider, and that you're storing your API key using
dotenv
. (If you don't, go and set up a free account by either.) If you're using this snippet, make sure the entire endpoint URL is in the.env
file, likehttps://eth-goerli.alchemyapi.io/v2/deadbeef_deadbeef_deadbeef
.If you're using ethers:
This is a very basic function - there's a good chance that you'll want to add some functionality to it, like reloading contracts once there's a signer attached, or a
try/catch
for disconnecting the wallet on a failed connection attempt. From a UI perspecitve, there are also intermediate states that you'll want to handle, like connecting (to provide a spinner) and the like.Interacting With Wallets and Providers
Once you have a connected provider and/or wallet,
web3react
gives you a number of modules for interacting with the wallet. In any component interacting with the wallet, first importuseWeb3React
:Then destructure the relevant modules from
web3react
like so:We'll give a detailed rundown of what you can do with this in the section called Web3React API Reference. Before we get to that, we'll detail how to disconnect a wallet.
Disconnecting a Wallet
web3react
provides two different functions for disconnecting a wallet:deactivate
andclose
before. You can seedeactivate
in the code above - it can be destructured directly from the object you get when you calluserWeb3React
.close
is a custom function that most, but not all, wallets have. Unfortunately, it can be hard to know which to call when. In addition, MetaMask and the injected connectors do not have aclose
function, which can cause an error if it is called, and some wallets will not be cleared from the DOM unlessclose
is called, meaning that you cannot rely ondeactivate
. As a result, you may want to implement a genericdisconnectWallet
function which ensures that the right functions are called for disconnecting the wallet fully.Web3React API Reference
From here we'll do our best to describe any function in
web3react
that we're aware of, what it does, and how to use it.It's worth noting that since we're using
web3react
, all wallet interactions should now go throughtweb3react
usingweb3react
's syntax, as opposed to using the wallet's own API.connector
This object represents that
connector
that is connected right now. It extendsAbstract-Connector
.A number of the functions that
connector
exposes are also available directly throughuseWeb3React()
, even without usingconnector
directly. The rest of the functions thatconnector
expose can change from wallet to wallet - not everything here will necessarily be implemented in every wallet, and the functions might behave differently from wallet to wallet. One particularly pertinent example is theconnector.close()
functions, which removes a wallet from the DOM. This can mean needing various checks when calling these functions, such as atry/catch
or anif
checking which wallet is connected (if connector === walletConnect
, for example). We discussed disconnecting wallets in more detail above, in the Disconnecting a Wallet section.If a
supportedChainIds
array was provided when the wallet was instantiated (highly recommended), it is also available throughconnector.supportedChainIds
.In addition, there are a number of outputs sent to the console from
connector
. You can see these in the abstract class here.account
(Also accessible as
connector.getAccount()
)This is the address of the connected wallet - anytime you need the user's address, you can use
account
.activate
(Also accessible as
connector.activate(<WALLET_NAME>)
)Used when connecting a new wallet. If you have a
walletConnect
built fromWalletConnectConnector
:This is used in the example above for connecting a wallet.
active
A boolean showing if the user has a connected wallet, useful in conditional rendering.
chainId
(Also accessible as
connector.getChainId()
)Number representation of the
chainId
the user is connected to. Useful for only displaying modals when the user is connected to supported networks, or displaying an alert when they are not.For a comprehensive list of chains (both production and test networks), see ChainId Network.
deactivate
(Also accessible as
connector.deactivate()
)Deactivate disconnects the wallet from the app. It is important to note that if the wallet has injected an iframe (like Portis, for example), it will not be removed from the DOM, which can lead to issues if the user tries to reconnect. In these cases, it is better to use
connector.close()
. We'll discuss disconnecting the user separately.error
The
error
library exposes a number of potential errors that it recognizes. It does not stop execution when they are triggered, but rather gives the architect room to catch each error and customize how the applicaiton should react to it.Most of these errors vary from wallet to wallet, and unfortunately not all are documented. We'll give one example to give an idea of how they work and then list errors from MetaMask/injected providers and Portis.
Most dApps support some chains (generally mainnet and some testnets), but not all. Properly identifying if the user is on a supported chain is a crticial part of good UX in a dApp.
web3-react
exposes aUnsupportedChainIdError
that allows you to detect when a user is on an unsupported chain.This error relies on an array of supported chains being supplied when the wallet is instantiated. You can pass in a supportedChainIds as an argument when instantiating a waller, an array of numbers. This, or something like it, is either a mandatory or optional argument for every connector/wallet that
web3-react
recognizes. This example assumes you've passed in an array with supported chains.First, import the error:
Then destructure it from the
useWeb3React
object:Now if you wanted to have a specific reaction in the app, you can now use it. (Remember that
supportedChainIds
is an optional argument.) Here's one example:The other globally available error is
StaleConnectorError
.There are also custom errors depending on your wallet. We'll list MetaMask's:
NoEthereumProviderError
: used when an injected provider is expected to be there but isn't (example)UserRejectedRequestError
: used if the user rejects a transaction through the injected providerPortis does not have any custom errors.
provider
(Also accessible as
connector.getProvider()
)This is the same as the concept of a provider in web3.js. It also contains a signer unlike the Ethers paradigm where the provider and signer are two separated entities. This means that when using web3, the
provider
is passed in at contract instantiation, but with Ethers a simple provider (for example, usingethers.getDefaultProvider()
) is sufficient for instantiating a contract, but theweb3react
provider will need to be connected to send transactions. (This might be a bit confusing. There is a dedicated section for working with contracts in Warp Core later.)setError
setError
takes anError
as an argument.Error
is a built-in TypeScript type:When called, it reloads
web3react
. This is used internally in the library when errors happen -web3react
will callsetError
and try to reload. You can also use this manually if you'd like to create a custom error which will then be available throughout the project.You can set a new error type like this
Then you can use that error anywhere in the app:
Custom Functions
In addition to the global functions above, some wallets (connectors) have their own unique functions exposed by
web3react
. These can be very important.close()
, for example, will fully clear DOM-based wallets from the DOM, whichdeactivate()
will not.If you'd like to find the custom functions for a given wallet, as of this writing you will need to actually look through the code of the connector to see what's there. The directory of all the connectors is here. For example, if we're looking to see if there are any special functions for Portis, we'd go to the Portis connector, where we'd see the global (public) functions (
activate
,getProvider
,getChainId
,getAccount
,deactivate
), and then also achangeNetwork
andclose
function.Conclusion
That's a wrap! We've detailed how you to integrate Web3React into your project, how to use it with the wallets you'd like, and what you can do with it once you're up and running.
We think Web3React is an excellent library, and hope this article helps people get started with it in their own projects!