"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CosmwasmPlatform = void 0;
const cosmwasm_stargate_1 = require("@cosmjs/cosmwasm-stargate");
const stargate_1 = require("@cosmjs/stargate");
const connect_sdk_1 = require("@wormhole-foundation/connect-sdk");
const chain_1 = require("./chain");
const constants_1 = require("./constants");
const types_1 = require("./types");
const connect_sdk_2 = require("@wormhole-foundation/connect-sdk");
const address_1 = require("./address");
const constants_2 = require("./constants");
/**
 * @category Cosmwasm
 */
class CosmwasmPlatform extends connect_sdk_1.PlatformContext {
    static _platform = types_1._platform;
    constructor(network, _config) {
        super(network, _config ?? (0, connect_sdk_1.networkPlatformConfigs)(network, CosmwasmPlatform._platform));
    }
    async getRpc(chain) {
        if (chain in this.config && this.config[chain].rpc)
            return await cosmwasm_stargate_1.CosmWasmClient.connect(this.config[chain].rpc);
        throw new Error("No configuration available for chain: " + chain);
    }
    getChain(chain, rpc) {
        if (chain in this.config)
            return new chain_1.CosmwasmChain(chain, this, rpc);
        throw new Error("No configuration available for chain: " + chain);
    }
    static getQueryClient = (rpc) => {
        return stargate_1.QueryClient.withExtensions(rpc["cometClient"], stargate_1.setupBankExtension, stargate_1.setupIbcExtension);
    };
    // cached channels from config if available
    static getIbcChannels(network, chain) {
        return constants_1.networkChainToChannels.has(network, chain)
            ? constants_1.networkChainToChannels.get(network, chain)
            : null;
    }
    static nativeTokenId(network, chain) {
        if (!this.isSupportedChain(chain))
            throw new Error(`invalid chain for CosmWasm: ${chain}`);
        return connect_sdk_1.Wormhole.chainAddress(chain, this.getNativeDenom(network, chain));
    }
    static isSupportedChain(chain) {
        const platform = (0, connect_sdk_2.chainToPlatform)(chain);
        return platform === CosmwasmPlatform._platform;
    }
    static isNativeTokenId(network, chain, tokenId) {
        if (!this.isSupportedChain(chain))
            return false;
        if (tokenId.chain !== chain)
            return false;
        const native = this.nativeTokenId(network, chain);
        return native == tokenId;
    }
    static async getDecimals(chain, rpc, token) {
        if ((0, connect_sdk_1.isNative)(token))
            return connect_sdk_1.decimals.nativeDecimals(CosmwasmPlatform._platform);
        const addrStr = new address_1.CosmwasmAddress(token).toString();
        const { decimals: numDecimals } = await rpc.queryContractSmart(addrStr, {
            token_info: {},
        });
        return numDecimals;
    }
    static async getBalance(chain, rpc, walletAddress, token) {
        if ((0, connect_sdk_1.isNative)(token)) {
            const [network, _] = await CosmwasmPlatform.chainFromRpc(rpc);
            const { amount } = await rpc.getBalance(walletAddress, this.getNativeDenom(network, chain));
            return BigInt(amount);
        }
        const addrStr = new address_1.CosmwasmAddress(token).toString();
        const { amount } = await rpc.getBalance(walletAddress, addrStr);
        return BigInt(amount);
    }
    static async getBalances(chain, rpc, walletAddress, tokens) {
        const client = CosmwasmPlatform.getQueryClient(rpc);
        const allBalances = await client.bank.allBalances(walletAddress);
        const [network, _] = await CosmwasmPlatform.chainFromRpc(rpc);
        const balancesArr = tokens.map((token) => {
            const address = (0, connect_sdk_1.isNative)(token)
                ? this.getNativeDenom(network, chain)
                : new address_1.CosmwasmAddress(token).toString();
            const balance = allBalances.find((balance) => balance.denom === address);
            const balanceBigInt = balance ? BigInt(balance.amount) : null;
            return { [address]: balanceBigInt };
        });
        return balancesArr.reduce((obj, item) => Object.assign(obj, item), {});
    }
    static getNativeDenom(network, chain) {
        return constants_1.chainToNativeDenoms.get(network, chain);
    }
    static async sendWait(chain, rpc, stxns) {
        const txhashes = [];
        for (const stxn of stxns) {
            const result = await rpc.broadcastTx(stxn);
            if (result.code !== 0)
                throw new Error(`Error sending transaction (${result.transactionHash}): ${result.rawLog}`);
            txhashes.push(result.transactionHash);
        }
        return txhashes;
    }
    static async getLatestBlock(rpc) {
        return await rpc.getHeight();
    }
    static async getLatestFinalizedBlock(rpc) {
        throw new Error("not implemented");
    }
    static chainFromChainId(chainMoniker) {
        const networkChainPair = connect_sdk_1.nativeChainIds.platformNativeChainIdToNetworkChain(CosmwasmPlatform._platform, chainMoniker);
        if (networkChainPair === undefined)
            throw new Error(`Unknown Cosmwasm chainId ${chainMoniker}`);
        const [network, chain] = networkChainPair;
        return [network, chain];
    }
    static async chainFromRpc(rpc) {
        const chainId = await rpc.getChainId();
        return this.chainFromChainId(chainId);
    }
    static async getCounterpartyChannel(sourceChannel, rpc) {
        const queryClient = CosmwasmPlatform.getQueryClient(rpc);
        const conn = await queryClient.ibc.channel.channel(constants_2.IBC_TRANSFER_PORT, sourceChannel);
        return conn.channel?.counterparty?.channelId ?? null;
    }
}
exports.CosmwasmPlatform = CosmwasmPlatform;
//# sourceMappingURL=platform.js.map