"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEVNET_ALPH_MINIMAL_CONSISTENCY_LEVEL = exports.TESTNET_ALPH_MINIMAL_CONSISTENCY_LEVEL = exports.MAINNET_ALPH_MINIMAL_CONSISTENCY_LEVEL = exports.TERRA_REDEEMED_CHECK_WALLET_ADDRESS = exports.MAX_VAA_DECIMALS = exports.WSOL_DECIMALS = exports.WSOL_ADDRESS = exports.assertEVMChain = exports.isEVMChain = exports.coalesceChainName = exports.coalesceChainId = exports.toChainName = exports.toChainId = exports.assertChain = exports.isChain = exports.CHAIN_ID_TO_NAME = exports.CHAIN_ID_ETHEREUM_ROPSTEN = exports.CHAIN_ID_ALEPHIUM = exports.CHAIN_ID_NEON = exports.CHAIN_ID_MOONBEAM = exports.CHAIN_ID_NEAR = exports.CHAIN_ID_CELO = exports.CHAIN_ID_KLAYTN = exports.CHAIN_ID_ACALA = exports.CHAIN_ID_KARURA = exports.CHAIN_ID_FANTOM = exports.CHAIN_ID_AURORA = exports.CHAIN_ID_ALGORAND = exports.CHAIN_ID_OASIS = exports.CHAIN_ID_AVAX = exports.CHAIN_ID_POLYGON = exports.CHAIN_ID_BSC = exports.CHAIN_ID_TERRA = exports.CHAIN_ID_ETH = exports.CHAIN_ID_SOLANA = exports.CHAIN_ID_UNSET = exports.CHAINS = void 0;
exports.CHAINS = {
    unset: 0,
    solana: 1,
    ethereum: 2,
    terra: 3,
    bsc: 4,
    polygon: 5,
    avalanche: 6,
    oasis: 7,
    algorand: 8,
    aurora: 9,
    fantom: 10,
    karura: 11,
    acala: 12,
    klaytn: 13,
    celo: 14,
    near: 15,
    moonbeam: 16,
    neon: 17,
    alephium: 255,
    ropsten: 10001,
};
// We don't specify the types of the below consts to be [[ChainId]]. This way,
// the inferred type will be a singleton (or literal) type, which is more precise and allows
// typescript to perform context-sensitive narrowing when checking against them.
// See the [[isEVMChain]] for an example.
exports.CHAIN_ID_UNSET = exports.CHAINS["unset"];
exports.CHAIN_ID_SOLANA = exports.CHAINS["solana"];
exports.CHAIN_ID_ETH = exports.CHAINS["ethereum"];
exports.CHAIN_ID_TERRA = exports.CHAINS["terra"];
exports.CHAIN_ID_BSC = exports.CHAINS["bsc"];
exports.CHAIN_ID_POLYGON = exports.CHAINS["polygon"];
exports.CHAIN_ID_AVAX = exports.CHAINS["avalanche"];
exports.CHAIN_ID_OASIS = exports.CHAINS["oasis"];
exports.CHAIN_ID_ALGORAND = exports.CHAINS["algorand"];
exports.CHAIN_ID_AURORA = exports.CHAINS["aurora"];
exports.CHAIN_ID_FANTOM = exports.CHAINS["fantom"];
exports.CHAIN_ID_KARURA = exports.CHAINS["karura"];
exports.CHAIN_ID_ACALA = exports.CHAINS["acala"];
exports.CHAIN_ID_KLAYTN = exports.CHAINS["klaytn"];
exports.CHAIN_ID_CELO = exports.CHAINS["celo"];
exports.CHAIN_ID_NEAR = exports.CHAINS["near"];
exports.CHAIN_ID_MOONBEAM = exports.CHAINS["moonbeam"];
exports.CHAIN_ID_NEON = exports.CHAINS["neon"];
exports.CHAIN_ID_ALEPHIUM = exports.CHAINS["alephium"];
exports.CHAIN_ID_ETHEREUM_ROPSTEN = exports.CHAINS["ropsten"];
exports.CHAIN_ID_TO_NAME = Object.entries(exports.CHAINS).reduce((obj, [name, id]) => {
    obj[id] = name;
    return obj;
}, {});
/**
 *
 * Returns true when called with a valid chain, and narrows the type in the
 * "true" branch to [[ChainId]] or [[ChainName]] thanks to the type predicate in
 * the return type.
 *
 * A typical use-case might look like
 * ```typescript
 * foo = isChain(c) ? doSomethingWithChainId(c) : handleInvalidCase()
 * ```
 */
function isChain(chain) {
    if (typeof chain === "number") {
        return chain in exports.CHAIN_ID_TO_NAME;
    }
    else {
        return chain in exports.CHAINS;
    }
}
exports.isChain = isChain;
/**
 *
 * Asserts that the given number or string is a valid chain, and throws otherwise.
 * After calling this function, the type of chain will be narrowed to
 * [[ChainId]] or [[ChainName]] thanks to the type assertion in the return type.
 *
 * A typical use-case might look like
 * ```typescript
 * // c has type 'string'
 * assertChain(c)
 * // c now has type 'ChainName'
 * ```
 */
function assertChain(chain) {
    if (!isChain(chain)) {
        if (typeof chain === "number") {
            throw Error(`Unknown chain id: ${chain}`);
        }
        else {
            throw Error(`Unknown chain: ${chain}`);
        }
    }
}
exports.assertChain = assertChain;
function toChainId(chainName) {
    return exports.CHAINS[chainName];
}
exports.toChainId = toChainId;
function toChainName(chainId) {
    return exports.CHAIN_ID_TO_NAME[chainId];
}
exports.toChainName = toChainName;
function coalesceChainId(chain) {
    // this is written in a way that for invalid inputs (coming from vanilla
    // javascript or someone doing type casting) it will always return undefined.
    return typeof chain === "number" && isChain(chain) ? chain : toChainId(chain);
}
exports.coalesceChainId = coalesceChainId;
function coalesceChainName(chain) {
    // this is written in a way that for invalid inputs (coming from vanilla
    // javascript or someone doing type casting) it will always return undefined.
    return toChainName(coalesceChainId(chain));
}
exports.coalesceChainName = coalesceChainName;
/**
 *
 * Returns true when called with an [[EVMChainId]] or [[EVMChainName]], and false otherwise.
 * Importantly, after running this check, the chain's type will be narrowed to
 * either the EVM subset, or the non-EVM subset thanks to the type predicate in
 * the return type.
 */
function isEVMChain(chain) {
    let chainId = coalesceChainId(chain);
    if (chainId === exports.CHAIN_ID_ETH ||
        chainId === exports.CHAIN_ID_BSC ||
        chainId === exports.CHAIN_ID_AVAX ||
        chainId === exports.CHAIN_ID_POLYGON ||
        chainId === exports.CHAIN_ID_OASIS ||
        chainId === exports.CHAIN_ID_AURORA ||
        chainId === exports.CHAIN_ID_FANTOM ||
        chainId === exports.CHAIN_ID_KARURA ||
        chainId === exports.CHAIN_ID_ACALA ||
        chainId === exports.CHAIN_ID_KLAYTN ||
        chainId === exports.CHAIN_ID_CELO ||
        chainId === exports.CHAIN_ID_MOONBEAM ||
        chainId === exports.CHAIN_ID_NEON ||
        chainId === exports.CHAIN_ID_ETHEREUM_ROPSTEN) {
        return isEVM(chainId);
    }
    else {
        return notEVM(chainId);
    }
}
exports.isEVMChain = isEVMChain;
/**
 *
 * Asserts that the given chain id or chain name is an EVM chain, and throws otherwise.
 * After calling this function, the type of chain will be narrowed to
 * [[EVMChainId]] or [[EVMChainName]] thanks to the type assertion in the return type.
 *
 */
function assertEVMChain(chain) {
    if (!isEVMChain(chain)) {
        throw Error(`Expected an EVM chain, but ${chain} is not`);
    }
}
exports.assertEVMChain = assertEVMChain;
exports.WSOL_ADDRESS = "So11111111111111111111111111111111111111112";
exports.WSOL_DECIMALS = 9;
exports.MAX_VAA_DECIMALS = 8;
exports.TERRA_REDEEMED_CHECK_WALLET_ADDRESS = "terra1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v";
////////////////////////////////////////////////////////////////////////////////
// Utilities
/**
 * The [[isEVM]] and [[notEVM]] functions improve type-safety in [[isEVMChain]].
 *
 * As it turns out, typescript type predicates are unsound on their own,
 * allowing us to write something like this:
 *
 * ```typescript
 * function unsafeCoerce(n: number): n is 1 {
 *   return true
 * }
 * ```
 *
 * which is completely bogus. This happens presumably because the typescript
 * authors think of the type predicate mechanism as an escape hatch mechanism.
 * We want a more principled function though, that keeps us honest.
 *
 * in [[isEVMChain]], checking that disjunctive boolean expression actually
 * refines the type of chainId in both branches. In the "true" branch,
 * the type of chainId is narrowed to exactly the EVM chains, so calling
 * [[isEVM]] on it will typecheck, and similarly the "false" branch for the negation.
 * However, if we extend the [[EVMChainId]] type with a new EVM chain, this
 * function will no longer compile until the condition is extended.
 */
/**
 *
 * Returns true when called with an [[EVMChainId]] or [[EVMChainName]], and fails to compile
 * otherwise
 */
function isEVM(_) {
    return true;
}
/**
 *
 * Returns false when called with a non-[[EVMChainId]] and non-[[EVMChainName]]
 * argument, and fails to compile otherwise
 */
function notEVM(_) {
    return false;
}
// This just serves as a type assertion to ensure that [[EVMChainName]] is a
// subset of [[ChainName]], since typescript provides no built-in way to express
// this.
function evm_chain_subset(e) {
    // will fail to compile if 'e' can't be typed as a [[ChainName]]
    return e;
}
exports.MAINNET_ALPH_MINIMAL_CONSISTENCY_LEVEL = 105;
exports.TESTNET_ALPH_MINIMAL_CONSISTENCY_LEVEL = 10;
exports.DEVNET_ALPH_MINIMAL_CONSISTENCY_LEVEL = 10;
