import { BigNumberish, Signer } from 'ethers' import { JsonRpcProvider, Provider } from '@ethersproject/providers' import { Erc20, Erc20__factory } from './abi/types' import { BigNumber } from '@ethersproject/bignumber' import { formatUnits, parseUnits } from 'ethers/lib/utils' class ERC20Contract { private erc20: Erc20 constructor(address: string, signerOrProvider: string | Signer | Provider) { if (typeof signerOrProvider !== 'string') { this.erc20 = Erc20__factory.connect(address, signerOrProvider) } else { const provider = new JsonRpcProvider(signerOrProvider) this.erc20 = Erc20__factory.connect(address, provider) } } async details(): Promise<{ name: string, symbol: string, decimals: number }> { const name = await this.erc20.callStatic.name() const symbol = await this.erc20.callStatic.symbol() const decimals = await this.decimals() return { name, symbol, decimals } } async balance(address: string): Promise { return await this.erc20.callStatic.balanceOf(address) } async balanceFormat(address: string): Promise { const decimals = await this.erc20.callStatic.decimals() const balance = await this.erc20.callStatic.balanceOf(address) return formatUnits(balance, decimals) } async transfer(to: string, amount: number): Promise { if (this.erc20.address === null) { throw new Error('invalid signer or provider') } const decimals = await this.decimals() const val = parseUnits(`${amount}`, decimals) const tx = await this.erc20.transfer(to, val) return tx.hash } async approve(spender: string, amount: BigNumberish): Promise { if (this.erc20.address === null) { throw new Error('invalid signer or provider') } const tx = await this.erc20.approve(spender, amount) return tx.hash } async allowance(owner: string, spender: string): Promise { return this.erc20.callStatic.allowance(owner, spender) } private async decimals(): Promise { let decimals: number try { decimals = await this.erc20.callStatic.decimals() } catch { decimals = 0 } return decimals } } export default ERC20Contract