import { AddressZero } from "@ethersproject/constants";
import { getDecimals, getName, getSymbol } from "../erc20/handler";
import { getExchangeTokens } from "../erc20/subgraph";
export const NATIVE_TOKENS = {
    1: {
        // Ethereum Mainnet
        name: "Ether",
        decimals: 18,
        symbol: "ETH"
    },
    11155111: {
        // Ethereum Sepolia
        name: "Ether",
        decimals: 18,
        symbol: "ETH"
    },
    8453: {
        // Base
        name: "Ether",
        decimals: 18,
        symbol: "ETH"
    },
    42161: {
        // Arbitrum
        name: "Ether",
        decimals: 18,
        symbol: "ETH"
    },
    10: {
        // Base
        name: "Ether",
        decimals: 18,
        symbol: "ETH"
    },
    84532: {
        // Base Sepolia
        name: "Ether",
        decimals: 18,
        symbol: "ETH"
    },
    11155420: {
        // Optimism Sepolia
        name: "Ether",
        decimals: 18,
        symbol: "ETH"
    },
    421614: {
        // Arbitrum Sepolia
        name: "Ether",
        decimals: 18,
        symbol: "ETH"
    },
    137: {
        // Polygon Mainnet
        name: "MATIC",
        decimals: 18,
        symbol: "MATIC"
    },
    80002: {
        // Polygon Amoy
        name: "MATIC",
        decimals: 18,
        symbol: "MATIC"
    },
    1234: {
        // Private Node
        name: "Ether",
        decimals: 18,
        symbol: "ETH"
    },
    31337: {
        // Local Hardhat
        name: "Ether",
        decimals: 18,
        symbol: "ETH"
    }
};
export class TokenInfoManager {
    static TokenInfos = new Map();
    static mapInitialized = new Map();
    _web3Lib;
    _subgraphUrl;
    _chainId;
    static InvalidAddresses = new Map();
    constructor(chainId, web3Lib, subgraphUrl) {
        if (!NATIVE_TOKENS[chainId]) {
            throw new Error(`Unexpected chainId value '${chainId}'`);
        }
        if (!TokenInfoManager.TokenInfos.has(chainId)) {
            const tokenInfos = new Map();
            tokenInfos.set(AddressZero, NATIVE_TOKENS[chainId]);
            TokenInfoManager.TokenInfos.set(chainId, tokenInfos);
        }
        if (!TokenInfoManager.mapInitialized.has(chainId)) {
            TokenInfoManager.mapInitialized.set(chainId, false);
        }
        if (!TokenInfoManager.InvalidAddresses.has(chainId)) {
            TokenInfoManager.InvalidAddresses.set(chainId, new Set());
        }
        this._web3Lib = web3Lib;
        this._subgraphUrl = subgraphUrl;
        this._chainId = chainId;
    }
    async getExchangeTokenInfo(tokenAddress) {
        await this.ensureInitialized();
        const tokenInfos = TokenInfoManager.TokenInfos.get(this._chainId);
        const invalidAddressesSet = TokenInfoManager.InvalidAddresses.get(this._chainId);
        const key = tokenAddress.toLowerCase();
        if (!tokenInfos.has(key) && !invalidAddressesSet.has(key)) {
            const args = {
                web3Lib: this._web3Lib,
                contractAddress: tokenAddress
            };
            try {
                const [decimals, name, symbol] = await Promise.all([
                    getDecimals(args),
                    getName(args),
                    getSymbol(args)
                ]);
                tokenInfos.set(key, {
                    decimals,
                    name,
                    symbol
                });
            }
            catch (error) {
                invalidAddressesSet.add(key);
            }
        }
        return tokenInfos.get(key);
    }
    async ensureInitialized() {
        const isInitialized = TokenInfoManager.mapInitialized.get(this._chainId);
        if (!isInitialized) {
            // Be sure we are initializing the map only one time per chainId
            TokenInfoManager.mapInitialized.set(this._chainId, true);
            const tokenInfos = TokenInfoManager.TokenInfos.get(this._chainId);
            // Get all tokens from subgraph
            const tokens = await getExchangeTokens(this._subgraphUrl);
            for (const token of tokens) {
                tokenInfos.set(token.address.toLowerCase(), {
                    decimals: parseInt(token.decimals),
                    name: token.name,
                    symbol: token.symbol
                });
            }
        }
    }
}
//# sourceMappingURL=tokenInfoManager.js.map