"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateWrappedOnInjective = exports.transferFromInjective = exports.redeemOnInjective = exports.submitVAAOnInjective = exports.getOriginalAssetInjective = exports.getIsWrappedAssetInjective = exports.getIsTransferCompletedInjective = exports.getForeignAssetInjective = exports.createWrappedOnInjective = exports.attestFromInjective = void 0;
const sdk_ts_1 = require("@injectivelabs/sdk-ts");
const cosmwasm_1 = require("../cosmwasm");
const utils_1 = require("../utils");
const js_base64_1 = require("js-base64");
/**
 * Creates attestation message
 * @param tokenBridgeAddress Address of Inj token bridge contract
 * @param walletAddress Address of wallet in inj format
 * @param asset Name or address of the asset to be attested
 * For native assets the asset string is the denomination.
 * For foreign assets the asset string is the inj address of the foreign asset
 * @returns Message to be broadcast
 */
function attestFromInjective(tokenBridgeAddress, walletAddress, asset) {
    return __awaiter(this, void 0, void 0, function* () {
        const nonce = Math.round(Math.random() * 100000);
        const isNativeAsset = cosmwasm_1.isNativeDenomInjective(asset);
        return sdk_ts_1.MsgExecuteContractCompat.fromJSON({
            contractAddress: tokenBridgeAddress,
            sender: walletAddress,
            exec: {
                msg: {
                    asset_info: isNativeAsset
                        ? {
                            native_token: { denom: asset },
                        }
                        : {
                            token: {
                                contract_addr: asset,
                            },
                        },
                    nonce: nonce,
                },
                action: "create_asset_meta",
            },
        });
    });
}
exports.attestFromInjective = attestFromInjective;
exports.createWrappedOnInjective = submitVAAOnInjective;
/**
 * Returns the address of the foreign asset
 * @param tokenBridgeAddress Address of token bridge contact
 * @param client Holds the wallet and signing information
 * @param originChain The chainId of the origin of the asset
 * @param originAsset The address of the origin asset
 * @returns The foreign asset address or null
 */
function getForeignAssetInjective(tokenBridgeAddress, client, originChain, originAsset) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const queryResult = yield client.fetchSmartContractState(tokenBridgeAddress, Buffer.from(JSON.stringify({
                wrapped_registry: {
                    chain: utils_1.coalesceChainId(originChain),
                    address: js_base64_1.fromUint8Array(originAsset),
                },
            })).toString("base64"));
            const parsed = utils_1.parseSmartContractStateResponse(queryResult);
            return parsed.address;
        }
        catch (e) {
            return null;
        }
    });
}
exports.getForeignAssetInjective = getForeignAssetInjective;
/**
 * Return if the VAA has been redeemed or not
 * @param tokenBridgeAddress The Injective token bridge contract address
 * @param signedVAA The signed VAA byte array
 * @param client Holds the wallet and signing information
 * @returns true if the VAA has been redeemed.
 */
function getIsTransferCompletedInjective(tokenBridgeAddress, signedVAA, client) {
    return __awaiter(this, void 0, void 0, function* () {
        const queryResult = yield client.fetchSmartContractState(tokenBridgeAddress, Buffer.from(JSON.stringify({
            is_vaa_redeemed: {
                vaa: js_base64_1.fromUint8Array(signedVAA),
            },
        })).toString("base64"));
        const parsed = utils_1.parseSmartContractStateResponse(queryResult);
        return parsed.is_redeemed;
    });
}
exports.getIsTransferCompletedInjective = getIsTransferCompletedInjective;
/**
 * Checks if the asset is a wrapped asset
 * @param tokenBridgeAddress The address of the Injective token bridge contract
 * @param client Connection/wallet information
 * @param assetAddress Address of the asset in Injective format
 * @returns true if asset is a wormhole wrapped asset
 */
function getIsWrappedAssetInjective(tokenBridgeAddress, client, assetAddress) {
    return __awaiter(this, void 0, void 0, function* () {
        const hexified = utils_1.tryNativeToHexString(assetAddress, "injective");
        const result = yield getForeignAssetInjective(tokenBridgeAddress, client, utils_1.CHAIN_ID_INJECTIVE, new Uint8Array(Buffer.from(hexified)));
        if (result === null) {
            return false;
        }
        return true;
    });
}
exports.getIsWrappedAssetInjective = getIsWrappedAssetInjective;
/**
 * Returns information about the asset
 * @param wrappedAddress Address of the asset in wormhole wrapped format (hex string)
 * @param client WASM api client
 * @returns Information about the asset
 */
function getOriginalAssetInjective(wrappedAddress, client) {
    return __awaiter(this, void 0, void 0, function* () {
        const chainId = utils_1.CHAIN_ID_INJECTIVE;
        if (cosmwasm_1.isNativeCosmWasmDenom(chainId, wrappedAddress)) {
            return {
                isWrapped: false,
                chainId,
                assetAddress: utils_1.hexToUint8Array(cosmwasm_1.buildTokenId(chainId, wrappedAddress)),
            };
        }
        try {
            const response = yield client.fetchSmartContractState(wrappedAddress, Buffer.from(JSON.stringify({
                wrapped_asset_info: {},
            })).toString("base64"));
            const parsed = utils_1.parseSmartContractStateResponse(response);
            return {
                isWrapped: true,
                chainId: parsed.asset_chain,
                assetAddress: new Uint8Array(Buffer.from(parsed.asset_address, "base64")),
            };
        }
        catch (_a) { }
        return {
            isWrapped: false,
            chainId: chainId,
            assetAddress: utils_1.hexToUint8Array(cosmwasm_1.buildTokenId(chainId, wrappedAddress)),
        };
    });
}
exports.getOriginalAssetInjective = getOriginalAssetInjective;
/**
 * Submits the supplied VAA to Injective
 * @param tokenBridgeAddress Address of Inj token bridge contract
 * @param walletAddress Address of wallet in inj format
 * @param signedVAA VAA with the attestation message
 * @returns Message to be broadcast
 */
function submitVAAOnInjective(tokenBridgeAddress, walletAddress, signedVAA) {
    return __awaiter(this, void 0, void 0, function* () {
        return sdk_ts_1.MsgExecuteContractCompat.fromJSON({
            contractAddress: tokenBridgeAddress,
            sender: walletAddress,
            exec: {
                msg: {
                    data: js_base64_1.fromUint8Array(signedVAA),
                },
                action: "submit_vaa",
            },
        });
    });
}
exports.submitVAAOnInjective = submitVAAOnInjective;
exports.redeemOnInjective = submitVAAOnInjective;
/**
 * Creates the necessary messages to transfer an asset
 * @param walletAddress Address of the Inj wallet
 * @param tokenBridgeAddress Address of the token bridge contract
 * @param tokenAddress Address of the token being transferred
 * @param amount Amount of token to be transferred
 * @param recipientChain Destination chain
 * @param recipientAddress Destination wallet address
 * @param relayerFee Relayer fee
 * @param payload Optional payload
 * @returns Transfer messages to be sent on chain
 */
function transferFromInjective(walletAddress, tokenBridgeAddress, tokenAddress, amount, recipientChain, recipientAddress, relayerFee = "0", payload = null) {
    return __awaiter(this, void 0, void 0, function* () {
        const recipientChainId = utils_1.coalesceChainId(recipientChain);
        const nonce = Math.round(Math.random() * 100000);
        const isNativeAsset = cosmwasm_1.isNativeDenomInjective(tokenAddress);
        const mk_action = payload
            ? "initiate_transfer_with_payload"
            : "initiate_transfer";
        const mk_initiate_transfer = (info) => payload
            ? {
                asset: {
                    amount,
                    info,
                },
                recipient_chain: recipientChainId,
                recipient: Buffer.from(recipientAddress).toString("base64"),
                fee: relayerFee,
                nonce,
                payload,
            }
            : {
                asset: {
                    amount,
                    info,
                },
                recipient_chain: recipientChainId,
                recipient: Buffer.from(recipientAddress).toString("base64"),
                fee: relayerFee,
                nonce,
            };
        return isNativeAsset
            ? [
                sdk_ts_1.MsgExecuteContractCompat.fromJSON({
                    contractAddress: tokenBridgeAddress,
                    sender: walletAddress,
                    exec: {
                        msg: {},
                        action: "deposit_tokens",
                    },
                    funds: { denom: tokenAddress, amount },
                }),
                sdk_ts_1.MsgExecuteContractCompat.fromJSON({
                    contractAddress: tokenBridgeAddress,
                    sender: walletAddress,
                    exec: {
                        msg: mk_initiate_transfer({
                            native_token: { denom: tokenAddress },
                        }),
                        action: mk_action,
                    },
                }),
            ]
            : [
                sdk_ts_1.MsgExecuteContractCompat.fromJSON({
                    contractAddress: tokenAddress,
                    sender: walletAddress,
                    exec: {
                        msg: {
                            spender: tokenBridgeAddress,
                            amount,
                            expires: {
                                never: {},
                            },
                        },
                        action: "increase_allowance",
                    },
                }),
                sdk_ts_1.MsgExecuteContractCompat.fromJSON({
                    contractAddress: tokenBridgeAddress,
                    sender: walletAddress,
                    exec: {
                        msg: mk_initiate_transfer({
                            token: { contract_addr: tokenAddress },
                        }),
                        action: mk_action,
                    },
                }),
            ];
    });
}
exports.transferFromInjective = transferFromInjective;
exports.updateWrappedOnInjective = submitVAAOnInjective;
