UNPKG

@broxus/js-bridge-essentials

Version:

Bridge JavaScript Essentials library

178 lines (177 loc) 6.59 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EvmTokenUtils = void 0; const contracts_1 = require("../../models/evm-token/contracts"); const cache = new Map(); const ttl = 30 * 1000; class EvmTokenUtils { static allowance(connection, params) { return (0, contracts_1.erc20Contract)(connection, params.tokenAddress) .methods.allowance(params.ownerAddress, params.spenderAddress) .call(); } static async approve(connection, params) { const req = (0, contracts_1.erc20Contract)(connection, params.tokenAddress).methods.approve(params.spenderAddress, params.amount); const gas = await req?.estimateGas({ from: params.from, type: params.type, }); return req?.send({ from: params.from, gas: gas.toString(), type: params.type, }); } /** @deprecated Use EvmTokenUtils.balance instead */ static getBalance(connection, address, ownerAddress) { return EvmTokenUtils.balance(connection, address, ownerAddress); } /** * Get EVM token balance by the given token and owner addresses * @param {Web3} connection * @param {string} address * @param {string} ownerAddress * @returns {Promise<string>} */ static balance(connection, address, ownerAddress) { return (0, contracts_1.erc20Contract)(connection, address).methods.balanceOf(ownerAddress).call(); } /** * * @param {Web3} connection * @param {string} address * @param {Forceable} options * @returns {Promise<EvmTokenData | undefined>} */ static async getDetails(connection, address, options) { const netId = await connection.eth.net.getId(); const cached = cache.get(`${netId}-${address.toLowerCase()}`); const abi = [ { name: 'decimals', type: 'uint8', }, { name: 'name', type: 'string', }, { name: 'symbol', type: 'string', }, { name: 'totalSupply', type: 'uint256', }, ]; const reducer = (acc, r, idx) => { if (r.result == null) { throw new Error(`Failed to get ${abi[idx].name} for token ${address}`); } if (typeof r.result === 'string') { const decoded = connection.eth.abi.decodeParameter(abi[idx].type, r.result); if (abi[idx].name === 'decimals') { acc.decimals = parseInt(BigInt(decoded).toString(), 10); return acc; } if (abi[idx].name === 'totalSupply') { acc.totalSupply = BigInt(decoded).toString(); return acc; } acc[abi[idx].name] = decoded; return acc; } throw new Error(`Failed to parse ${abi[idx].name} for token ${address}. Given result is not a string`); }; const fallback = async () => { const [decimals, name, symbol, totalSupply] = await Promise.all([ EvmTokenUtils.getDecimals(connection, address), EvmTokenUtils.getName(connection, address), EvmTokenUtils.getSymbol(connection, address), EvmTokenUtils.totalSupply(connection, address), ]); return { address, decimals, name, symbol, totalSupply }; }; if (cached && !options?.force) { if (Date.now() - cached.timestamp < ttl && cached.data) { const res = await cached.data; return res.reduce(reducer, {}); } } try { const contract = (0, contracts_1.erc20Contract)(connection, address); const batch = new contract.BatchRequest(); batch.add({ method: 'eth_call', params: [{ data: contract.methods.decimals().encodeABI(), to: address, }, 'latest'], }); batch.add({ method: 'eth_call', params: [{ data: contract.methods.name().encodeABI(), to: address, }, 'latest'], }); batch.add({ method: 'eth_call', params: [{ data: contract.methods.symbol().encodeABI(), to: address, }, 'latest'], }); batch.add({ method: 'eth_call', params: [{ data: contract.methods.totalSupply().encodeABI(), to: address, }, 'latest'], }); const req = batch.execute({ timeout: 30_000 }); cache.set(`${netId}-${address.toLowerCase()}`, { data: req, timestamp: Date.now() }); const res = await req; return res.reduce(reducer, {}); } catch (e) { return fallback(); } } /** * Get EVM token decimals by the given token address * @param {Web3} connection * @param {string} address * @returns {Promise<number>} */ static async getDecimals(connection, address) { const result = await (0, contracts_1.erc20Contract)(connection, address).methods.decimals().call(); return parseInt(BigInt(result).toString(), 10); } /** * Get EVM token symbol by the given token address * @param {Web3} connection * @param {string} address */ static getSymbol(connection, address) { return (0, contracts_1.erc20Contract)(connection, address).methods.symbol().call(); } /** * Get EVM token name by the given token address * @param {Web3} connection * @param {string} address */ static getName(connection, address) { return (0, contracts_1.erc20Contract)(connection, address).methods.name().call(); } /** * Get EVM token total supply by the given token address * @param {Web3} connection * @param {string} address * @returns {Promise<string>} */ static totalSupply(connection, address) { return (0, contracts_1.erc20Contract)(connection, address).methods.totalSupply().call(); } } exports.EvmTokenUtils = EvmTokenUtils;