import { getRPC } from "./chains";
import { state } from "./store";
/**
 * Helper to create a token key for the balances map
 */
export function getTokenKey(chain, address) {
    return `${chain}:${address}`.toLowerCase();
}
/**
 * Fetch balances for all tokens and store in tokenBalances map
 */
export const fetchAllTokenBalances = async (walletAddress, assets, rpcOverrides) => {
    if (!walletAddress || assets.length === 0) {
        state.tokenBalances = {};
        return;
    }
    // Solana addresses use Base58 encoding which excludes visually ambiguous
    // characters: 0 (zero), O (uppercase o), I (uppercase i), l (lowercase L).
    // Valid Solana public keys are 32-44 characters when Base58 encoded.
    const solanaRegex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
    const isSolanaWallet = solanaRegex.test(walletAddress);
    // Filter assets to only those matching wallet type
    const relevantAssets = assets.filter((asset) => {
        const isSolanaAsset = asset.runtime === "svm";
        return isSolanaWallet === isSolanaAsset;
    });
    // Fetch all balances in parallel
    const balancePromises = relevantAssets.map(async (token) => {
        try {
            const rpcUrl = getRPC(token.chain, rpcOverrides);
            if (!rpcUrl) {
                return { token, balance: 0n };
            }
            let balance = 0n;
            if (token.runtime === "evm") {
                balance = await fetchEvmBalances(rpcUrl, walletAddress, token.address);
            }
            else if (token.runtime === "svm") {
                balance = await fetchSolanaBalances(rpcUrl, walletAddress, token.address);
            }
            return { token, balance };
        }
        catch (error) {
            console.error(`Error fetching balance for ${token.symbol}:`, error);
            return { token, balance: 0n };
        }
    });
    const results = await Promise.all(balancePromises);
    // Build the balances map
    const newBalances = {};
    for (const { token, balance } of results) {
        const key = getTokenKey(token.chain, token.address);
        newBalances[key] = balance;
    }
    state.tokenBalances = newBalances;
    // Also update fromTokenBalance for backward compatibility
    if (state.fromToken) {
        const fromKey = getTokenKey(state.fromToken.chain, state.fromToken.address);
        state.fromTokenBalance = newBalances[fromKey] || 0n;
    }
};
export const fetchTokenBalance = async (walletAddress, token, rpcOverrides) => {
    if (!walletAddress) {
        state.fromTokenBalance = 0n;
        return 0n;
    }
    // Solana addresses use Base58 encoding which excludes visually ambiguous
    // characters: 0 (zero), O (uppercase o), I (uppercase i), l (lowercase L).
    // Valid Solana public keys are 32-44 characters when Base58 encoded.
    const solanaRegex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
    const isSolanaWallet = solanaRegex.test(walletAddress);
    const isSolanaChain = state.fromToken.chain === "Solana";
    if (isSolanaWallet !== isSolanaChain) {
        state.fromTokenBalance = 0n;
        return 0n;
    }
    try {
        const rpcUrl = getRPC(token.chain, rpcOverrides);
        if (!rpcUrl) {
            console.warn(`No RPC URL configured for chain: ${token.chain}`);
            state.fromTokenBalance = 0n;
            return 0n;
        }
        let balance;
        if (token.runtime === "evm") {
            balance = await fetchEvmBalances(rpcUrl, walletAddress, token.address);
        }
        else if (token.runtime === "svm") {
            balance = await fetchSolanaBalances(rpcUrl, walletAddress, token.address);
        }
        state.fromTokenBalance = balance;
        return balance;
    }
    catch (error) {
        console.error("Error fetching token balance:", error);
        state.fromTokenBalance = 0n;
        return 0n;
    }
};
export async function fetchEvmBalances(rpcUrl, walletAddress, tokenAddress) {
    try {
        // Fetch ERC20 token balance using balanceOf(address)
        const balanceOfSelector = "0x70a08231"; // balanceOf(address)
        const paddedAddress = walletAddress.slice(2).padStart(64, "0");
        const callData = balanceOfSelector + paddedAddress;
        const response = await fetch(rpcUrl, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                jsonrpc: "2.0",
                method: "eth_call",
                params: [
                    {
                        to: tokenAddress,
                        data: callData,
                    },
                    "latest",
                ],
                id: 1,
            }),
        });
        const data = await response.json();
        if (data.error) {
            console.error("RPC error:", data.error);
            return 0n;
        }
        return BigInt(data.result);
    }
    catch (error) {
        console.error("Error fetching EVM balance:", error);
        return 0n;
    }
}
export async function fetchSolanaBalances(rpcUrl, walletAddress, tokenAddress) {
    try {
        // Fetch SPL token balance for specific mint
        const response = await fetch(rpcUrl, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                jsonrpc: "2.0",
                method: "getTokenAccountsByOwner",
                params: [
                    walletAddress,
                    { mint: tokenAddress },
                    { encoding: "jsonParsed" },
                ],
                id: 1,
            }),
        });
        const data = await response.json();
        if (data.error) {
            console.error("RPC error:", data.error);
            return 0n;
        }
        // Sum all token accounts for this mint (usually just one)
        const accounts = data.result?.value || [];
        let totalBalance = 0n;
        for (const account of accounts) {
            const amount = account.account?.data?.parsed?.info?.tokenAmount?.amount;
            if (amount) {
                totalBalance += BigInt(amount);
            }
        }
        return totalBalance;
    }
    catch (error) {
        console.error("Error fetching Solana balance:", error);
        return 0n;
    }
}
//# sourceMappingURL=balances.js.map
