jcwallet/src/standards/ERC20Standard.ts

190 lines
5.0 KiB
TypeScript

import Web3 from "web3";
import { abiERC20 } from "../abis/abiERC20";
import { BN, toUtf8 } from "ethereumjs-util";
import { universalChainCb } from "../util/chain.util";
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<BN> {
const contract = new this.web3.eth.Contract(abiERC20, address);
return new Promise<BN>((resolve, reject) => {
contract.methods
.balanceOf(selectedAddress)
.call({ from: selectedAddress }, (error: Error, result: BN) => {
/* istanbul ignore if */
if (error) {
reject(error);
return;
}
console.log("getBalanceOf success " + result);
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<string> {
const contract = new this.web3.eth.Contract(abiERC20, address);
return new Promise<string>((resolve, reject) => {
contract.methods.decimals().call((error: Error, result: 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<string> {
const contract = new this.web3.eth.Contract(abiERC20, address);
return new Promise<string>((resolve, reject) => {
contract.methods.symbol().call((error: Error, result: 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<string>((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: 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,
estimate,
}: {
address: string;
from: string;
to: string;
amount: number | string;
gas?: number;
estimate: number;
}) {
const contract = new this.web3.eth.Contract(abiERC20, address);
const amountBN = Web3.utils.toBN(Web3.utils.toWei(amount + ""));
if (!gas) {
gas = await contract.methods.transfer(to, "0").estimateGas();
}
gas = (gas * 1.1) | 1;
if (estimate) {
return jc.wallet.generateGasShow(gas);
}
const logData = {
gas,
title: "transfer",
details: [
{
address,
from,
to,
value: amountBN,
id: "0",
},
],
};
return universalChainCb(
logData,
contract.methods.transfer(to, amountBN).send({
from,
gas,
})
);
}
}