Typed general ERC20 contract with Ethers.js and Typescript
Ok, so you are using ethers.js to develop your app. You want to interact with an external ERC20 contract, and you want types.
This tutorial will show you how to get types in ethers.js for ERC20-contracts without running your own full development environments like Hardhat.
Creating a Contract
with ethers.js
A suggested way to initialize a Contract
with ethers.js for a specific method like balanceOf
for an ERC-20 is this:
const provider = new providers.JsonRpcProvider(...);
const address = "0x...";
const abi = ["function balanceOf(address owner) view returns (uint256)"];
const erc20 = new ethers.Contract(address, abi, provider);
This will let you call erc20.balanceOf(...)
and interact with the actual contract on chain.
It works, but the problem is that this approach does not provide typescript types.
How can we get the types?
One method is running a full developer environment like HardHat and use TypeChain to get the types. But to be fair, these approaches seem more geared towards usecases when you are writing your own solidity contracts, and not when you are just interfacing with generic ERC-20 contracts.
Getting a typed Contract
with abi-types-generator
A simple way to get a typed ethers.js Contract
is by generating the types from a standard ERC-20 json ABI.
- Download the generic erc20.abi.json and put it in your project
- Install ethereum-abi-types-generator as a dev-dependency
yarn add ethereum-abi-types-generator --dev
- Run this command to create types
npx abi-types-generator erc20.abi.json --provider=ethers_v5
Now you should see the types in an erc20.ts
file in you project.
Go back to your code and do a few imports. Make sure to write as unknown as Erc20
to avoid type errors.
import * as erc20Abi from "./erc20.abi.json";
import { Erc20 } from "./erc20";
const erc20 = new ethers.Contract(
address,
erc20Abi,
provider
) as unknown as Erc20;
And voila, now you have a properly typed generic ERC-20 contract for ethers.js.
const balance = await erc20.balanceOf(MY_WALLET);
console.log("balance: ", balance); // BigNumber { _hex: '0x06d1cee24e0209' ... }
Hope this helped!