"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SUPPORTED_CHAIN_NAMES = exports.supportedChains = void 0;
exports.getPublicClient = getPublicClient;
exports.getAddress = getAddress;
const viem_1 = require("viem");
const chains_1 = require("viem/chains");
const parser_1 = require("../config/parser");
exports.supportedChains = {
    ethereum: chains_1.mainnet,
    base: chains_1.base,
    bsc: chains_1.bsc,
    arbitrum: chains_1.arbitrum,
    optimism: chains_1.optimism,
    sepolia: chains_1.sepolia,
    polygon: chains_1.polygon,
    base_sepolia: chains_1.baseSepolia,
};
exports.SUPPORTED_CHAIN_NAMES = Object.keys(exports.supportedChains);
function getPublicClient(chainName) {
    const chain = exports.supportedChains[chainName];
    if (!chain)
        throw new Error(`Unsupported chain: ${chainName}`);
    const config = (0, parser_1.loadConfig)();
    const customRpcRaw = config.web3?.rpc_urls?.[chainName];
    const transports = [];
    if (customRpcRaw) {
        if (Array.isArray(customRpcRaw)) {
            customRpcRaw.forEach(url => {
                if (url.trim())
                    transports.push((0, viem_1.http)(url.trim()));
            });
        }
        else if (typeof customRpcRaw === 'string' && customRpcRaw.trim()) {
            transports.push((0, viem_1.http)(customRpcRaw.trim()));
        }
    }
    // Fallback public RPCs (Top tier from Chainlist.org prioritized)
    if (!customRpcRaw) {
        if (chainName === 'ethereum') {
            transports.push((0, viem_1.http)('https://ethereum-rpc.publicnode.com', { timeout: 5000 }));
            transports.push((0, viem_1.http)('https://eth.llamarpc.com', { timeout: 5000 }));
            transports.push((0, viem_1.http)('https://rpc.ankr.com/eth', { timeout: 5000 }));
        }
        else if (chainName === 'bsc') {
            transports.push((0, viem_1.http)('https://bsc-rpc.publicnode.com', { timeout: 5000 }));
            transports.push((0, viem_1.http)('https://bsc-dataseed.binance.org', { timeout: 5000 }));
        }
        else if (chainName === 'base') {
            transports.push((0, viem_1.http)('https://base-rpc.publicnode.com', { timeout: 5000 }));
            transports.push((0, viem_1.http)('https://mainnet.base.org', { timeout: 5000 }));
        }
        else if (chainName === 'arbitrum') {
            transports.push((0, viem_1.http)('https://arbitrum-one-rpc.publicnode.com', { timeout: 5000 }));
            transports.push((0, viem_1.http)('https://arb1.arbitrum.io/rpc', { timeout: 5000 }));
        }
        else if (chainName === 'optimism') {
            transports.push((0, viem_1.http)('https://optimism-rpc.publicnode.com', { timeout: 5000 }));
            transports.push((0, viem_1.http)('https://mainnet.optimism.io', { timeout: 5000 }));
        }
        else if (chainName === 'sepolia') {
            transports.push((0, viem_1.http)('https://ethereum-sepolia-rpc.publicnode.com', { timeout: 5000 }));
            transports.push((0, viem_1.http)('https://rpc.sepolia.org', { timeout: 5000 }));
        }
        else if (chainName === 'polygon') {
            transports.push((0, viem_1.http)('https://polygon-rpc.publicnode.com', { timeout: 5000 }));
            transports.push((0, viem_1.http)('https://polygon.llamarpc.com', { timeout: 5000 }));
            transports.push((0, viem_1.http)('https://polygon-rpc.com', { timeout: 5000 }));
        }
    }
    // Always append the default public RPC (like cloudflare) as the last resort
    transports.push((0, viem_1.http)(undefined, { timeout: 5000 }));
    // @ts-ignore
    return (0, viem_1.createPublicClient)({
        chain,
        transport: (0, viem_1.fallback)(transports, { rank: false }),
        batch: {
            multicall: true
        }
    });
}
// Fetch address from Policy API which proxies to Signer
async function getAddress() {
    const token = process.env.INTERNAL_AUTH_TOKEN;
    try {
        const res = await fetch('http://127.0.0.1:3001/address', {
            headers: { 'Authorization': `Bearer ${token}` }
        });
        if (!res.ok)
            throw new Error('Vault is locked or unavailable');
        const data = await res.json();
        return data.address;
    }
    catch (err) {
        throw new Error(`Failed to fetch address: ${err.message}`);
    }
}
