"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const hardhat_1 = require("hardhat");
const deploymentConfig_1 = require("../helpers/deploymentConfig");
const utils_1 = require("../helpers/utils");
const configureAccessControls = async (methods, accessControlManagerAddress, caller, target, hre) => {
    const commands = await Promise.all(methods.map(async (method) => {
        const callerAddress = await (0, utils_1.toAddress)(caller, hre);
        const targetAddress = await (0, utils_1.toAddress)(target, hre);
        return [
            {
                contract: accessControlManagerAddress,
                signature: "giveCallPermission(address,string,address)",
                argTypes: ["address", "string", "address"],
                parameters: [targetAddress, method, callerAddress],
                value: 0,
            },
        ];
    }));
    return commands.flat();
};
const configureXVSTokenMintCapCommands = async (xvsToken, minterAddress) => {
    const command = [
        {
            contract: xvsToken,
            signature: "setMintCap(address,uint256)",
            argTypes: ["address", "uint256"],
            parameters: [minterAddress, "100000000000000000000"],
            value: 0,
        },
    ];
    return command.flat();
};
const executeBridgeCommands = async (target, hre, deployer) => {
    const signer = await hardhat_1.ethers.getSigner(deployer);
    console.log("Executing Bridge commands");
    const methods = deploymentConfig_1.bridgeConfig[hre.network.name].methods;
    for (let i = 0; i < methods.length; i++) {
        const entry = methods[i];
        const { method, args } = entry;
        console.log(method);
        const iface = new hardhat_1.ethers.utils.Interface([`function ${method}`]);
        const data = iface.encodeFunctionData(method, args);
        const tx = await signer.sendTransaction({
            to: target.address,
            data: data,
        });
        await tx.wait();
    }
};
const func = async function (hre) {
    const { deployments, getNamedAccounts } = hre;
    const { deploy } = deployments;
    const { deployer } = await getNamedAccounts();
    const preconfiguredAddresses = await (0, deploymentConfig_1.getPreConfiguredAddresses)(hre.network.name);
    const proxyOwnerAddress = await (0, utils_1.toAddress)(preconfiguredAddresses.NormalTimelock, hre);
    const accessControlManager = await hardhat_1.ethers.getContract("AccessControlManager");
    const resilientOracle = await hardhat_1.ethers.getContract("ResilientOracle");
    const XVS = await deploy("XVS", {
        from: deployer,
        contract: "XVS",
        args: [accessControlManager.address],
        autoMine: true,
        log: true,
    });
    const XVSProxyOFTDest = await deploy("XVSProxyOFTDest", {
        from: deployer,
        contract: "XVSProxyOFTDest",
        args: [XVS.address, 8, preconfiguredAddresses.LzEndpoint, resilientOracle.address],
        autoMine: true,
        log: true,
    });
    const XVSBridgeAdmin = await deploy("XVSBridgeAdmin", {
        from: deployer,
        args: [XVSProxyOFTDest.address],
        contract: "XVSBridgeAdmin",
        proxy: {
            owner: proxyOwnerAddress,
            proxyContract: "OpenZeppelinTransparentProxy",
            execute: {
                methodName: "initialize",
                args: [accessControlManager.address],
            },
            upgradeIndex: 0,
        },
        log: true,
        autoMine: true,
    });
    const bridge = await hardhat_1.ethers.getContract("XVSProxyOFTDest");
    const bridgeAdmin = await hardhat_1.ethers.getContract("XVSBridgeAdmin");
    const xvs = await hardhat_1.ethers.getContract("XVS");
    await executeBridgeCommands(bridge, hre, deployer);
    const removeArray = new Array(deploymentConfig_1.xvsBridgeMethodsDest.length).fill(true);
    let tx = await bridgeAdmin.upsertSignature(deploymentConfig_1.xvsBridgeMethodsDest, removeArray);
    await tx.wait();
    tx = await xvs.transferOwnership(preconfiguredAddresses.NormalTimelock);
    await tx.wait();
    tx = await bridge.transferOwnership(XVSBridgeAdmin.address);
    await tx.wait();
    tx = await bridgeAdmin.transferOwnership(preconfiguredAddresses.NormalTimelock);
    await tx.wait();
    console.log(`Bridge Admin owner ${deployer} sucessfully changed to ${preconfiguredAddresses.NormalTimelock}. Please accept the ownership.`);
    const commands = [
        ...(await configureAccessControls(deploymentConfig_1.xvsBridgeMethodsDest, accessControlManager.address, preconfiguredAddresses.NormalTimelock, XVSBridgeAdmin.address, hre)),
        ...(await configureAccessControls(deploymentConfig_1.xvsTokenPermissions, accessControlManager.address, XVSProxyOFTDest.address, XVS.address, hre)),
        ...(await configureAccessControls(deploymentConfig_1.XVSBridgeAdminMethods, accessControlManager.address, preconfiguredAddresses.NormalTimelock, XVSBridgeAdmin.address, hre)),
        ...(await configureAccessControls(deploymentConfig_1.XVSTokenDestMethods, accessControlManager.address, preconfiguredAddresses.NormalTimelock, XVS.address, hre)),
        {
            contract: XVSBridgeAdmin.address,
            signature: "acceptOwnership()",
            parameters: [],
            value: 0,
        },
        {
            contract: XVSBridgeAdmin.address,
            signature: "setTrustedRemoteAddress(uint16,bytes)",
            parameters: [preconfiguredAddresses.LzVirtualChainIdL, "0xDestAddress"],
            value: 0,
        },
        ...(await configureXVSTokenMintCapCommands(XVS.address, XVSProxyOFTDest.address)),
    ];
    console.log("Please propose a Multisig tx with the following commands:");
    console.log(JSON.stringify(commands.map(c => ({ target: c.contract, signature: c.signature, params: c.parameters, value: c.value }))));
};
func.tags = ["XVSBridgeDest"];
func.skip = async (hre) => hre.network.live === false || hre.network.name === "bsctestnet" || hre.network.name === "bscmainnet";
exports.default = func;
