"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isLocalhost = exports.increaseTime = exports.chunk = exports.mintTokens = exports.getUserTokenBalance = exports.convertToCurrencyDecimals = exports.approveUnderlyingIfFirstInteraction = exports.getAssetPrices = exports.convertListSymbolToAddress = exports.getContractAddress = exports.getAllAssetSymbols = exports.convertSymbolToAddress = exports.convertAddressListToSymbol = exports.convertAddressToSymbol = exports.cache = void 0;
const ethers_1 = require("ethers");
const constants_1 = require("./constants");
const contract_getters_1 = require("./contract-getters");
const decode_bytecode_1 = require("./decode-bytecode");
const node_ts_cache_1 = require("node-ts-cache");
const node_ts_cache_storage_memory_1 = require("node-ts-cache-storage-memory");
exports.cache = new node_ts_cache_1.CacheContainer(new node_ts_cache_storage_memory_1.MemoryStorage());
function isMainnetFork(network) {
    return network == "main" || network == "localhost";
}
function convertAddressToSymbol(asset, network) {
    if (!asset) {
        throw new Error("convertAddressToSymbol missing asset");
    }
    asset = asset.toLowerCase();
    switch (network) {
        // goerli, optimism_goerli, sepolia will use our custom deployments
        case "goerli":
            return constants_1.REVERSE_GOERLI_CUSTOM_ASSET_MAPPINGS.get(asset);
        case "sepolia":
            return constants_1.REVERSE_SEPOLIA_CUSTOM_ASSET_MAPPINGS.get(asset);
        // forks and networks will use real addresses
        case "localhost":
        case "main":
            return constants_1.REVERSE_MAINNET_ASSET_MAPPINGS.get(asset);
        case "optimism_localhost":
        case "optimism":
            return constants_1.REVERSE_OPTIMISM_ASSET_MAPPINGS.get(asset);
    }
    throw Error(`Asset=${asset} not found on network ${network}`);
}
exports.convertAddressToSymbol = convertAddressToSymbol;
function convertAddressListToSymbol(assets, network) {
    return assets.map((el) => convertAddressToSymbol(el, network));
}
exports.convertAddressListToSymbol = convertAddressListToSymbol;
function convertSymbolToAddress(asset, network) {
    if (!asset) {
        throw new Error("Convert symbol to address missing asset");
    }
    asset = asset.toUpperCase();
    if (asset == "ETH") {
        return constants_1.ZERO_ADDRESS;
    }
    switch (network) {
        // goerli, optimism_goerli, sepolia will use our custom deployments
        case "goerli":
        case "sepolia":
            return constants_1.deployments[asset][network].address;
        // forks and networks will use real addresses
        case "localhost":
        case "main":
            return constants_1.MAINNET_ASSET_MAPPINGS.get(asset);
        case "optimism_localhost":
        case "optimism":
            return constants_1.OPTIMISM_ASSET_MAPPINGS.get(asset);
    }
    throw Error(`Asset=${asset} not found on network ${network}`);
}
exports.convertSymbolToAddress = convertSymbolToAddress;
function getAllAssetSymbols(network) {
    switch (network) {
        // goerli, optimism_goerli, sepolia will use our custom depl
        case "goerli":
            return Array.from(constants_1.GOERLI_CUSTOM_ASSET_MAPPINGS.keys());
        case "sepolia":
            return Array.from(constants_1.SEPOLIA_CUSTOM_ASSET_MAPPINGS.keys());
        // forks and networks will use real addresses
        case "localhost":
        case "main":
            return Array.from(constants_1.MAINNET_ASSET_MAPPINGS.keys());
        case "optimism_localhost":
        case "optimism":
            return Array.from(constants_1.OPTIMISM_ASSET_MAPPINGS.keys());
    }
    throw Error(`network=${network} not found`);
}
exports.getAllAssetSymbols = getAllAssetSymbols;
function getContractAddress(contractName, network) {
    return constants_1.deployments[contractName][network].address;
}
exports.getContractAddress = getContractAddress;
function convertListSymbolToAddress(assets, network) {
    return assets.map((el) => convertSymbolToAddress(el, network));
}
exports.convertListSymbolToAddress = convertListSymbolToAddress;
async function getAssetPricesContractCall(params) {
    const cacheKey = "asset-prices";
    const cachedTotalMarkets = await exports.cache.getItem(cacheKey);
    if (cachedTotalMarkets) {
        return cachedTotalMarkets;
    }
    const provider = contract_getters_1.getProvider(params.providerRpc, params.test);
    const { abi, bytecode, } = require("./artifacts/contracts/analytics-utilities/asset/GetAllAssetPrices.sol/GetAllAssetPrices.json");
    let _addressProvider = constants_1.deployments.LendingPoolAddressesProvider[params.network || "main"].address;
    const assets = convertListSymbolToAddress(params.assets, params.network).filter((el) => el !== undefined);
    let [data] = await decode_bytecode_1.decodeConstructorBytecode(abi, bytecode, provider, [
        _addressProvider,
        assets,
    ]);
    let assetPrices = new Map();
    assets.map((asset, idx) => {
        assetPrices.set(asset, data[idx]);
    });
    await exports.cache.setItem(cacheKey, assetPrices, { ttl: 60 });
    return assetPrices;
}
async function getAssetPrices(params) {
    switch (params.network) {
        // subgraph asset prices not work for these network
        case "goerli":
        case "sepolia":
        case "localhost":
        case "optimism_localhost":
            return getAssetPricesContractCall(params);
        case "optimism":
        case "main":
            // TODO: get asset prices from subgraph
            return;
    }
}
exports.getAssetPrices = getAssetPrices;
/**
 *
 */
async function approveUnderlyingIfFirstInteraction(signer, underlying, spender) {
    let _underlying = new ethers_1.ethers.Contract(underlying, [
        "function approve(address spender, uint256 value) external returns (bool success)",
        "function allowance(address owner, address spender) external view returns (uint256)",
    ], signer);
    let allowance = await _underlying
        .connect(signer)
        .allowance(await signer.getAddress(), spender);
    if (allowance.eq(ethers_1.BigNumber.from("0"))) {
        return await _underlying
            .connect(signer)
            .approve(spender, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); //approves uint256 max
    }
}
exports.approveUnderlyingIfFirstInteraction = approveUnderlyingIfFirstInteraction;
exports.convertToCurrencyDecimals = async (tokenAddress, amount, test, providerRpc) => {
    if (tokenAddress == constants_1.ZERO_ADDRESS) { //native eth
        return ethers_1.ethers.utils.parseUnits(amount, 18);
    }
    const token = await contract_getters_1.getIErc20Detailed(tokenAddress, providerRpc, test);
    let decimals = (await token.decimals()).toString();
    return ethers_1.ethers.utils.parseUnits(amount, decimals);
};
exports.getUserTokenBalance = async (tokenAddress, user, test, providerRpc) => {
    const provider = contract_getters_1.getProvider(providerRpc, test);
    if (tokenAddress == constants_1.ZERO_ADDRESS) { //native eth
        return provider.getBalance(user);
    }
    const token = await contract_getters_1.getIErc20Detailed(tokenAddress, providerRpc, test);
    return token.balanceOf(user);
};
async function mintTokens(params) {
    const token = await contract_getters_1.getMintableERC20({
        tokenSymbol: params.token,
        signer: params.signer,
        network: params.network,
        test: params.test,
        providerRpc: params.providerRpc,
    });
    let tx;
    try {
        tx = await token.mint(ethers_1.ethers.utils.parseUnits("1000000.0", await token.decimals()));
    }
    catch (error) {
        console.error("DEV: mint tokens failed with", error);
        throw new Error(error);
    }
    return tx;
}
exports.mintTokens = mintTokens;
exports.chunk = (arr, chunkSize) => {
    return arr.reduce((prevVal, currVal, currIndx, array) => !(currIndx % chunkSize)
        ? prevVal.concat([array.slice(currIndx, currIndx + chunkSize)])
        : prevVal, []);
};
exports.increaseTime = async (provider, secondsToIncrease) => {
    await provider.send("evm_increaseTime", [secondsToIncrease]);
    await provider.send("evm_mine", []);
};
exports.isLocalhost = (network) => {
    return network == "localhost" || network == "optimism_localhost";
};
//# sourceMappingURL=utils.js.map