"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertJettonToken = exports.convertSplTokens = exports.convertERC20 = exports.addTokens = exports.getTokenById = exports.hasTokenId = exports.findTokenByAddressInCurrency = exports.findTokenByAddress = exports.findTokenById = exports.findTokenByTicker = exports.listTokenTypesForCryptoCurrency = exports.listTokensForCryptoCurrency = exports.listTokens = exports.__clearAllLists = exports.createTokenHash = void 0;
const cardanoNative_1 = __importDefault(require("./data/cardanoNative"));
const currencies_1 = require("./currencies");
const ton_jetton_1 = __importDefault(require("./data/ton-jetton"));
const _11155111_1 = require("./data/evm/11155111");
const stellar_1 = __importDefault(require("./data/stellar"));
const vip180_1 = __importDefault(require("./data/vip180"));
const esdt_1 = __importDefault(require("./data/esdt"));
const asa_1 = __importDefault(require("./data/asa"));
const _137_1 = require("./data/evm/137");
const _146_1 = require("./data/evm/146");
const trc10_1 = __importDefault(require("./data/trc10"));
const trc20_1 = __importDefault(require("./data/trc20"));
const _1_1 = require("./data/evm/1");
const _56_1 = require("./data/evm/56");
const filecoin_erc20_1 = __importDefault(require("./data/filecoin-erc20"));
const spl_1 = __importDefault(require("./data/spl"));
const apt_coin_1 = __importDefault(require("./data/apt_coin"));
const apt_fungible_asset_1 = __importDefault(require("./data/apt_fungible_asset"));
const live_env_1 = require("@ledgerhq/live-env");
const emptyArray = [];
const tokensArray = [];
const tokensArrayWithDelisted = [];
const tokensByCryptoCurrency = {};
const tokensByCryptoCurrencyWithDelisted = {};
const tokensById = {};
const tokensByTicker = {};
const tokensByAddress = {};
const tokensByCurrencyAddress = {};
const tokenListHashes = new Set();
// Ethereum mainnet tokens
addTokens(_1_1.tokens.map(convertERC20));
// Ethereum Sepolia testnet tokens
addTokens(_11155111_1.tokens.map(convertERC20));
// Polygon tokens
addTokens(_137_1.tokens.map(convertERC20));
// Binance Smart Chain tokens
addTokens(_56_1.tokens.map(convertERC20));
// Tron tokens
addTokens(trc10_1.default.map(convertTRONTokens("trc10")));
addTokens(trc20_1.default.map(convertTRONTokens("trc20")));
// Algoland tokens
addTokens(asa_1.default.map(convertAlgorandASATokens));
// MultiversX tokens
addTokens(esdt_1.default.map(convertMultiversXESDTTokens));
// Cardano tokens
addTokens(cardanoNative_1.default.map(convertCardanoNativeTokens));
// Stellar tokens
addTokens(stellar_1.default.map(convertStellarTokens));
// VeChain tokens
addTokens(vip180_1.default.map(convertVechainToken));
// Ton tokens
addTokens(ton_jetton_1.default.map(convertJettonToken));
// Filecoin tokens
addTokens(filecoin_erc20_1.default.map(convertERC20));
// Solana tokens
addTokens(spl_1.default.map(convertSplTokens));
// Sonic
addTokens(_146_1.tokens.map(convertERC20));
if ((0, live_env_1.getEnv)("APTOS_ENABLE_TOKENS")) {
    // Aptos Legacy Coin tokens
    addTokens(apt_coin_1.default.map(convertAptCoinTokens));
    // Aptos fungible assets tokens
    addTokens(apt_fungible_asset_1.default.map(convertAptFaTokens));
}
const defaultTokenListOptions = {
    withDelisted: false,
};
function createTokenHash(token) {
    return token
        ? `${token.id}${token.contractAddress}${token.delisted}${token.ticker}${token.ledgerSignature}`
        : "";
}
exports.createTokenHash = createTokenHash;
/**
 * Only for jest purpose, clean object to be empty
 * @param obj
 */
const __clearObject = (obj) => {
    for (const key in obj) {
        delete obj[key];
    }
};
/**
 * Only for jest purpose, clear all the init list
 */
function __clearAllLists() {
    tokensArray.length = 0;
    tokensArrayWithDelisted.length = 0;
    __clearObject(tokensByCryptoCurrency);
    __clearObject(tokensByCryptoCurrencyWithDelisted);
    __clearObject(tokensById);
    __clearObject(tokensByTicker);
    __clearObject(tokensByAddress);
    __clearObject(tokensByCurrencyAddress);
    tokenListHashes.clear();
}
exports.__clearAllLists = __clearAllLists;
/**
 *
 */
function listTokens(options) {
    const { withDelisted } = { ...defaultTokenListOptions, ...options };
    return withDelisted ? tokensArrayWithDelisted : tokensArray;
}
exports.listTokens = listTokens;
/**
 *
 */
function listTokensForCryptoCurrency(currency, options) {
    const { withDelisted } = { ...defaultTokenListOptions, ...options };
    if (withDelisted) {
        return tokensByCryptoCurrencyWithDelisted[currency.id] || emptyArray;
    }
    return tokensByCryptoCurrency[currency.id] || emptyArray;
}
exports.listTokensForCryptoCurrency = listTokensForCryptoCurrency;
/**
 *
 */
function listTokenTypesForCryptoCurrency(currency) {
    return listTokensForCryptoCurrency(currency).reduce((acc, cur) => {
        const tokenType = cur.tokenType.replace("_", " ");
        if (acc.indexOf(tokenType) < 0) {
            return [...acc, tokenType];
        }
        return acc;
    }, []);
}
exports.listTokenTypesForCryptoCurrency = listTokenTypesForCryptoCurrency;
/**
 *
 */
function findTokenByTicker(ticker) {
    return tokensByTicker[ticker];
}
exports.findTokenByTicker = findTokenByTicker;
/**
 *
 */
function findTokenById(id) {
    return tokensById[id];
}
exports.findTokenById = findTokenById;
let deprecatedDisplayed = false;
function findTokenByAddress(address) {
    if (!deprecatedDisplayed) {
        deprecatedDisplayed = true;
        console.warn("findTokenByAddress is deprecated. use findTokenByAddressInCurrency");
    }
    return tokensByAddress[address.toLowerCase()];
}
exports.findTokenByAddress = findTokenByAddress;
function findTokenByAddressInCurrency(address, currencyId) {
    return tokensByCurrencyAddress[currencyId + ":" + address.toLowerCase()];
}
exports.findTokenByAddressInCurrency = findTokenByAddressInCurrency;
/**
 *
 */
const hasTokenId = (id) => id in tokensById;
exports.hasTokenId = hasTokenId;
/**
 *
 */
function getTokenById(id) {
    const currency = findTokenById(id);
    if (!currency) {
        throw new Error(`token with id "${id}" not found`);
    }
    return currency;
}
exports.getTokenById = getTokenById;
function removeTokenFromArray(array, tokenId) {
    if (array && array.length > 0) {
        const index = array.findIndex(currentToken => currentToken && currentToken.id === tokenId);
        if (index === -1)
            return array;
        return array.splice(index, 1);
    }
}
function removeTokenFromRecord(record, key) {
    tokenListHashes.delete(record[key]);
    delete record[key];
}
/**
 * Delete previous token entry to all array
 * @param token
 */
function removeTokenFromAllLists(token) {
    const { id, contractAddress, parentCurrency, ticker } = token;
    const lowCaseContract = contractAddress.toLowerCase();
    removeTokenFromRecord(tokensById, id);
    removeTokenFromRecord(tokensByCurrencyAddress, parentCurrency.id + ":" + lowCaseContract);
    removeTokenFromRecord(tokensByAddress, lowCaseContract);
    removeTokenFromRecord(tokensByTicker, ticker);
    removeTokenFromArray(tokensArray, id);
    removeTokenFromArray(tokensArrayWithDelisted, id);
    removeTokenFromArray(tokensByCryptoCurrency[parentCurrency.id], id);
    removeTokenFromArray(tokensByCryptoCurrencyWithDelisted[parentCurrency.id], id);
}
function addTokens(list) {
    list.forEach(token => {
        if (!token)
            return;
        const tokenHash = createTokenHash(token);
        if (tokenListHashes.has(tokenHash))
            return;
        /**
         * We clean all the reference of an existing token, if an hash doesn't  match.
         * Like this we can update any change from a already added token coming from Dynamic CAL
         * and maintain it up to date without having to release a new version of LLD or LLM
         */
        const { id, contractAddress, parentCurrency, delisted, ticker } = token;
        if (tokensById[id])
            removeTokenFromAllLists(token);
        const lowCaseContract = contractAddress.toLowerCase();
        if (!delisted)
            tokensArray.push(token);
        tokensArrayWithDelisted.push(token);
        tokensById[id] = token;
        if (!tokensByTicker[ticker]) {
            tokensByTicker[ticker] = token;
        }
        tokensByAddress[lowCaseContract] = token;
        tokensByCurrencyAddress[parentCurrency.id + ":" + lowCaseContract] = token;
        if (!(parentCurrency.id in tokensByCryptoCurrency)) {
            tokensByCryptoCurrency[parentCurrency.id] = [];
        }
        if (!(parentCurrency.id in tokensByCryptoCurrencyWithDelisted)) {
            tokensByCryptoCurrencyWithDelisted[parentCurrency.id] = [];
        }
        if (!delisted)
            tokensByCryptoCurrency[parentCurrency.id].push(token);
        tokensByCryptoCurrencyWithDelisted[parentCurrency.id].push(token);
        tokenListHashes.add(tokenHash);
    });
}
exports.addTokens = addTokens;
function convertERC20([parentCurrencyId, token, ticker, magnitude, name, ledgerSignature, contractAddress, disableCountervalue, delisted,]) {
    const parentCurrency = (0, currencies_1.findCryptoCurrencyById)(parentCurrencyId);
    if (!parentCurrency) {
        return;
    }
    const tokenType = parentCurrencyId === "bsc" ? "bep20" : "erc20";
    return {
        type: "TokenCurrency",
        id: `${parentCurrencyId}/${tokenType}/${token}`,
        ledgerSignature,
        contractAddress,
        parentCurrency,
        tokenType,
        name,
        ticker,
        delisted,
        disableCountervalue: !!parentCurrency.isTestnetFor || !!disableCountervalue,
        units: [
            {
                name,
                code: ticker,
                magnitude,
            },
        ],
    };
}
exports.convertERC20 = convertERC20;
function convertAlgorandASATokens([id, abbr, name, contractAddress, precision,]) {
    const parentCurrency = (0, currencies_1.getCryptoCurrencyById)("algorand");
    return {
        type: "TokenCurrency",
        id: `algorand/asa/${id}`,
        contractAddress,
        parentCurrency,
        tokenType: "asa",
        name,
        ticker: abbr,
        disableCountervalue: false,
        units: [
            {
                name,
                code: abbr,
                magnitude: precision,
            },
        ],
    };
}
function convertVechainToken([tokenIdenfitier, ticker, name, contractAddress, precision,]) {
    return {
        type: "TokenCurrency",
        id: `vechain/vip180/${tokenIdenfitier}`,
        contractAddress: contractAddress,
        parentCurrency: (0, currencies_1.getCryptoCurrencyById)("vechain"),
        tokenType: "vip180",
        name,
        ticker,
        disableCountervalue: false,
        units: [
            {
                name,
                code: ticker,
                magnitude: precision,
            },
        ],
    };
}
function convertTRONTokens(type) {
    return ([id, abbr, name, contractAddress, precision, delisted, ledgerSignature]) => {
        const parentCurrency = (0, currencies_1.getCryptoCurrencyById)("tron");
        return {
            type: "TokenCurrency",
            id: `tron/${type}/${id}`,
            contractAddress,
            parentCurrency,
            tokenType: type,
            name,
            ticker: abbr,
            delisted,
            disableCountervalue: false,
            ledgerSignature,
            units: [
                {
                    name,
                    code: abbr,
                    magnitude: precision,
                },
            ],
        };
    };
}
function convertMultiversXESDTTokens([ticker, identifier, decimals, signature, name,]) {
    const MULTIVERSX_ESDT_CONTRACT = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u";
    // const parentCurrency = getCryptoCurrencyById("multiversx");
    const parentCurrency = (0, currencies_1.getCryptoCurrencyById)("elrond");
    return {
        type: "TokenCurrency",
        id: `multiversx/esdt/${identifier}`,
        contractAddress: MULTIVERSX_ESDT_CONTRACT,
        ledgerSignature: signature,
        parentCurrency,
        tokenType: "esdt",
        disableCountervalue: false,
        name,
        ticker,
        units: [
            {
                name,
                code: name,
                magnitude: decimals,
            },
        ],
    };
}
function convertSplTokens([id, network, name, symbol, address, decimals,]) {
    return {
        type: "TokenCurrency",
        id,
        contractAddress: address,
        parentCurrency: (0, currencies_1.getCryptoCurrencyById)(network),
        name,
        tokenType: "spl",
        ticker: symbol,
        disableCountervalue: false,
        units: [
            {
                name,
                code: symbol,
                magnitude: decimals,
            },
        ],
    };
}
exports.convertSplTokens = convertSplTokens;
function convertAptosTokens(tokenType, [id, ticker, name, address, decimals, delisted]) {
    return {
        type: "TokenCurrency",
        id,
        contractAddress: address,
        parentCurrency: (0, currencies_1.getCryptoCurrencyById)("aptos"),
        name,
        tokenType,
        ticker,
        disableCountervalue: false,
        delisted,
        units: [
            {
                name,
                code: ticker,
                magnitude: decimals,
            },
        ],
    };
}
function convertAptCoinTokens(token) {
    return convertAptosTokens("coin", token);
}
function convertAptFaTokens(token) {
    return convertAptosTokens("fungible_asset", token);
}
function convertCardanoNativeTokens([parentCurrencyId, policyId, assetName, name, ticker, decimals, delisted,]) {
    const assetId = policyId + assetName;
    const parentCurrency = (0, currencies_1.getCryptoCurrencyById)(parentCurrencyId);
    if (!parentCurrency) {
        return;
    }
    return {
        type: "TokenCurrency",
        id: `${parentCurrencyId}/native/${assetId}`,
        // Tracking and accounting of native tokens is natively supported by cardano ledger.
        // As there's no contract for native tokens, using unique assetId in place of contractAddress
        contractAddress: assetId,
        parentCurrency,
        tokenType: "native",
        name,
        ticker,
        delisted,
        disableCountervalue: false,
        units: [
            {
                name,
                code: ticker,
                magnitude: decimals,
            },
        ],
    };
}
function convertStellarTokens([assetCode, assetIssuer, assetType, name, precision,]) {
    const parentCurrency = (0, currencies_1.getCryptoCurrencyById)("stellar");
    // FIXME: to be discussed with CAL service as values are Uppercase IRL
    return {
        type: "TokenCurrency",
        id: `stellar/asset/${assetCode.toUpperCase()}:${assetIssuer.toUpperCase()}`,
        contractAddress: assetIssuer.toUpperCase(),
        parentCurrency,
        tokenType: assetType,
        name,
        ticker: assetCode,
        disableCountervalue: false,
        units: [
            {
                name,
                code: assetCode,
                magnitude: precision,
            },
        ],
    };
}
function convertJettonToken([address, name, ticker, magnitude, delisted]) {
    const parentCurrency = (0, currencies_1.findCryptoCurrencyById)("ton");
    if (!parentCurrency) {
        return;
    }
    return {
        type: "TokenCurrency",
        id: "ton/jetton/" + address.toLocaleLowerCase(),
        contractAddress: address,
        parentCurrency,
        tokenType: "jetton",
        name,
        ticker,
        delisted,
        disableCountervalue: false,
        units: [
            {
                name,
                code: ticker,
                magnitude,
            },
        ],
    };
}
exports.convertJettonToken = convertJettonToken;
//# sourceMappingURL=tokens.js.map