"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.monitorWalletBalance = monitorWalletBalance;
exports.fetchWalletBalance = fetchWalletBalance;
exports.getAddressTokensBalances = getAddressTokensBalances;
const ethers_1 = require("ethers");
const helpers_1 = require("./helpers");
const logger_1 = require("./logger");
const helpers_2 = require("../pricer/helpers");
const types_1 = require("../pricer/types");
/**
 * Periodically check the wallet balance of the service for the given network
 *
 * @param {string} serviceName
 * @param {NetworkConfig}  network
 * @param {string}  address
 * @param {string}  token
 * @param {number}  walletCheckIntervalSec
 * @param {Rpc}  rpc
 * @param {any}  prometheusBalance
 * @param {any}  balances
 */
async function monitorWalletBalance(serviceName, network, address, token, walletCheckIntervalSec, rpc, prometheusBalance, balances) {
    logger_1.logger.debug(`💳 Monitoring wallet ${address} balance on ${network.name} network`);
    while (true) {
        const balance = await fetchWalletBalance(address, rpc, network, token);
        if (balances) {
            balances[network.id] = balance;
        }
        prometheusBalance.set({
            name: serviceName,
            sourceNetwork: network.name,
            token,
            address,
        }, Number(balance));
        await (0, helpers_1.sleepRandom)(walletCheckIntervalSec, walletCheckIntervalSec + 6, 'Wait before checking wallet balance');
    }
}
async function fetchWalletBalance(address, rpc, network, tokenAddress) {
    // Get the token symbol strictly for logging purposes
    let symbol;
    try {
        symbol = (0, helpers_2.getAssetNameByAddress)(network.id, tokenAddress);
    }
    catch (error) {
        logger_1.logger.error({ error: error.message, address, network: network.id, token: tokenAddress }, 'Could not fetch asset name by address');
    }
    try {
        const isNative = types_1.idToNativeAssetName[network.id] === symbol;
        const balance = await (isNative
            ? rpc.fetchWalletBalance(network.id, address, symbol)
            : rpc.fetchTokenBalance(network.id, address, tokenAddress, symbol));
        if (!balance) {
            return ethers_1.BigNumber.from(0);
        }
        return balance;
    }
    catch (error) {
        logger_1.logger.error({ error: error.message, address, network: network.id, token: tokenAddress }, 'Error fetching wallet balance; defaulting to 0');
        return ethers_1.BigNumber.from(0);
    }
}
async function getAddressTokensBalances(address, enabledNetworks, rpc, enabledAssets = []) {
    const balances = {};
    for (const [_, network] of enabledNetworks) {
        const tokens = { ...network.tokens };
        balances[network.id] = {};
        // Insert a native currency to fetch balance since it's configured out for most networks via contracts config
        if (tokens[types_1.idToNativeAssetName[network.id]] === undefined) {
            tokens[types_1.idToNativeAssetName[network.id]] = ethers_1.ethers.constants.AddressZero;
        }
        for (const tokenName in tokens) {
            if (!enabledAssets.includes(tokenName)) {
                logger_1.logger.debug({
                    address,
                    network: network.id,
                    tokenName,
                }, 'Token is not enabled, skipping balance check');
                continue;
            }
            const tokenAddress = tokens[tokenName];
            if (!tokenAddress ||
                tokenAddress === 'N/A' ||
                (types_1.idToNativeAssetName[network.id] !== tokenName && tokenAddress === ethers_1.ethers.constants.AddressZero)) {
                continue;
            }
            const balance = await fetchWalletBalance(address, rpc, network, tokenAddress);
            balances[network.id][tokenName] = ethers_1.ethers.utils.formatEther(balance);
        }
    }
    return balances;
}
//# sourceMappingURL=wallet.js.map