190 lines
5.0 KiB
TypeScript
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,
|
|
})
|
|
);
|
|
}
|
|
}
|