import Web3 = require("../lib/web3.min"); import { abiERC20 } from "../abis/abiERC20"; export class ERC20Standard { private web3: Web3; constructor(web3: Web3) { this.web3 = web3; } /** * Get balance or count for current account on specific asset contract. * * @param address - Asset ERC20 contract address. * @param selectedAddress - Current account public address. * @returns Promise resolving to BN object containing balance for current account on specific asset contract. */ async getBalanceOf( address: string, selectedAddress: string ): Promise { const contract = new this.web3.eth.Contract(abiERC20, address); return new Promise((resolve, reject) => { contract.methods .balanceOf(selectedAddress) .call( { from: selectedAddress }, (error: Error, result: Web3.utils.BN) => { /* istanbul ignore if */ if (error) { reject(error); return; } resolve(result); } ); }); } /** * Query for the decimals for a given ERC20 asset. * * @param address - ERC20 asset contract string. * @returns Promise resolving to the 'decimals'. */ async getTokenDecimals(address: string): Promise { const contract = new this.web3.eth.Contract(abiERC20, address); return new Promise((resolve, reject) => { contract.methods .decimals() .call((error: Error, result: Web3.utils.BN | string) => { /* istanbul ignore if */ if (error) { reject(error); return; } resolve(result.toString()); }); }); } /** * Query for symbol for a given ERC20 asset. * * @param address - ERC20 asset contract address. * @returns Promise resolving to the 'symbol'. */ async getTokenSymbol(address: string): Promise { const contract = new this.web3.eth.Contract(abiERC20, address); return new Promise((resolve, reject) => { contract.methods .symbol() .call((error: Error, result: Web3.utils.BN | string) => { /* istanbul ignore if */ if (error) { reject(error); return; } resolve(result.toString()); }); }); // Signature for calling `symbol()` // const payload = { to: address, data: '0x95d89b41' }; // return new Promise((resolve, reject) => { // this.web3.eth.call(payload, undefined, (error: Error, result: string) => { // /* istanbul ignore if */ // if (error) { // reject(error); // return; // } // // Parse as string // try { // const decoded = Web3.utils.hexToUtf8(result); // if (decoded) { // console.log('decoded') // resolve(decoded); // return; // } // } catch { // // Ignore error // } // // Parse as bytes // try { // const utf8 = Web3.utils.toUtf8(result); // console.log('utf8') // resolve(utf8); // return; // } catch { // // Ignore error // } // reject(new Error('Failed to parse token symbol')); // }); // }); } /** * Query if a contract implements an interface. * * @param address - Asset contract address. * @param userAddress - The public address for the currently active user's account. * @returns Promise resolving an object containing the standard, decimals, symbol and balance of the given contract/userAddress pair. */ async getDetails( address: string, userAddress?: string ): Promise<{ standard: string; symbol: string | undefined; decimals: string | undefined; balance: Web3.utils.BN | undefined; }> { const [decimals, symbol] = await Promise.all([ this.getTokenDecimals(address), this.getTokenSymbol(address), ]); let balance; if (userAddress) { balance = await this.getBalanceOf(address, userAddress); } return { decimals, symbol, balance, standard: "ERC20", }; } async transfer({ address, from, to, amount, gas, }: { address: string; from: string; to: string; amount: number | string; gas?: number; }) { const contract = new this.web3.eth.Contract(abiERC20, address); amount = Web3.utils.toBN(Web3.utils.toWei(amount + "")); return contract.methods.transfer(to, amount).send({ from, gas: gas || 1000000, }); } }