"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveContractFromSymbol = exports.getL2TokenAddresses = void 0;
exports.fetchTokenInfo = fetchTokenInfo;
exports.resolveSymbolOnChain = resolveSymbolOnChain;
exports.getCoingeckoTokenIdByAddress = getCoingeckoTokenIdByAddress;
exports.getTokenBalance = getTokenBalance;
exports.isBridgedUsdc = isBridgedUsdc;
exports.isStablecoin = isStablecoin;
exports.getTokenInfo = getTokenInfo;
exports.getUsdcSymbol = getUsdcSymbol;
exports.getL1TokenAddress = getL1TokenAddress;
const tslib_1 = require("tslib");
const assert_1 = tslib_1.__importDefault(require("assert"));
const ethers_1 = require("ethers");
const constants = tslib_1.__importStar(require("../constants"));
const typechain_1 = require("../typechain");
const NetworkUtils_1 = require("./NetworkUtils");
const TypeGuards_1 = require("./TypeGuards");
const AddressUtils_1 = require("./AddressUtils");
const { TOKEN_SYMBOLS_MAP, CHAIN_IDs, TOKEN_EQUIVALENCE_REMAPPING } = constants;
async function fetchTokenInfo(address, signerOrProvider) {
    const token = new ethers_1.Contract(address, typechain_1.ERC20__factory.abi, signerOrProvider);
    const [symbol, decimals] = await Promise.all([token.symbol(), token.decimals()]);
    return { address: AddressUtils_1.EvmAddress.from(address), symbol, decimals };
}
const getL2TokenAddresses = (l1TokenAddress, l1ChainId = CHAIN_IDs.MAINNET) => {
    return Object.values(TOKEN_SYMBOLS_MAP).find((details) => {
        return details.addresses[l1ChainId] === l1TokenAddress;
    })?.addresses;
};
exports.getL2TokenAddresses = getL2TokenAddresses;
function resolveSymbolOnChain(chainId, symbol) {
    const token = TOKEN_SYMBOLS_MAP[symbol];
    if (!(0, TypeGuards_1.isDefined)(token) || !(0, TypeGuards_1.isDefined)(token.addresses[chainId])) {
        const network = (0, NetworkUtils_1.getNetworkName)(chainId);
        throw new Error(`Unable to find token ${symbol} on ${network} (chain ID ${chainId}`);
    }
    const { decimals, addresses } = token;
    const address = (0, AddressUtils_1.toAddressType)(addresses[chainId], chainId);
    (0, assert_1.default)(address.isEVM() || address.isSVM());
    return { symbol, decimals, address };
}
const resolveContractFromSymbol = (symbol, chainId, tokenMapping = TOKEN_SYMBOLS_MAP) => {
    return Object.values(tokenMapping).find((details) => {
        return details.symbol.toLowerCase() === symbol.toLowerCase();
    })?.addresses[chainId];
};
exports.resolveContractFromSymbol = resolveContractFromSymbol;
function getCoingeckoTokenIdByAddress(address, chainId) {
    const token = getTokenInfo((0, AddressUtils_1.toAddressType)(address, chainId), chainId);
    return TOKEN_SYMBOLS_MAP[token.symbol].coingeckoId;
}
function getTokenBalance(address, tokenAddress, signerOrProvider, blockTag = "latest") {
    const token = typechain_1.ERC20__factory.connect(tokenAddress, signerOrProvider);
    return token.balanceOf(address, { blockTag });
}
function isBridgedUsdc(tokenSymbol) {
    return !!constants.BRIDGED_USDC_SYMBOLS.find((bridgedUsdcSymbol) => bridgedUsdcSymbol.toLowerCase() === tokenSymbol.toLowerCase());
}
function isStablecoin(tokenSymbol) {
    return constants.STABLE_COIN_SYMBOLS.some((stablecoinSymbol) => stablecoinSymbol.toLowerCase() === tokenSymbol.toLowerCase());
}
function getTokenInfo(l2Token, chainId, tokenMapping = TOKEN_SYMBOLS_MAP) {
    const address = l2Token.toNative();
    let tokenObject = Object.values(tokenMapping).find(({ addresses }) => addresses[chainId] === address);
    if (!tokenObject) {
        throw new Error(`Unable to resolve token info for ${address} on chain ${chainId}`);
    }
    if ((0, NetworkUtils_1.chainIsL1)(chainId)) {
        const l1TokenSymbol = TOKEN_EQUIVALENCE_REMAPPING[tokenObject.symbol] ?? tokenObject.symbol;
        tokenObject = tokenMapping[l1TokenSymbol];
    }
    return { address: l2Token, symbol: tokenObject.symbol, decimals: tokenObject.decimals };
}
function getUsdcSymbol(l2Token, chainId) {
    const IterableTokenSymbolsMap = TOKEN_SYMBOLS_MAP;
    return ["USDC", "USDbC", "USDC.e"].find((token) => IterableTokenSymbolsMap[token]?.addresses?.[chainId] === l2Token.toNative());
}
function getL1TokenAddress(l2TokenAddress, chainId) {
    if ((0, NetworkUtils_1.chainIsL1)(chainId)) {
        (0, assert_1.default)(l2TokenAddress.isEVM());
        return l2TokenAddress;
    }
    const tokenObject = Object.values(TOKEN_SYMBOLS_MAP).find(({ addresses }) => l2TokenAddress.toNative() === addresses[chainId]);
    const l1TokenAddress = tokenObject?.addresses[(0, NetworkUtils_1.chainIsProd)(chainId) ? CHAIN_IDs.MAINNET : CHAIN_IDs.SEPOLIA];
    if (!l1TokenAddress) {
        throw new Error(`getL1TokenAddress: Unable to resolve l1 token for L2 token ${l2TokenAddress} on chain ${chainId}`);
    }
    return AddressUtils_1.EvmAddress.from(l1TokenAddress);
}
//# sourceMappingURL=TokenUtils.js.map