"use strict";
// This script creates ALT for a given burn token used in SVM Sponsored CCTP bridge.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const anchor = __importStar(require("@coral-xyz/anchor"));
const anchor_1 = require("@coral-xyz/anchor");
const spl_token_1 = require("@solana/spl-token");
const web3_js_1 = require("@solana/web3.js");
const yargs_1 = __importDefault(require("yargs"));
const helpers_1 = require("yargs/helpers");
const web3_v1_1 = require("../../../src/svm/web3-v1");
// Set up the provider and programs
const provider = anchor_1.AnchorProvider.env();
anchor.setProvider(provider);
const program = (0, web3_v1_1.getSponsoredCctpSrcPeripheryProgram)(provider);
const tokenMessengerMinterV2Program = (0, web3_v1_1.getTokenMessengerMinterV2Program)(provider);
const messageTransmitterV2Program = (0, web3_v1_1.getMessageTransmitterV2Program)(provider);
// Parse arguments
const argv = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv)).option("burnToken", {
    type: "string",
    demandOption: false,
    default: (0, web3_v1_1.isSolanaDevnet)(provider) ? web3_v1_1.SOLANA_USDC_DEVNET : web3_v1_1.SOLANA_USDC_MAINNET,
    describe: "Burn token public key, defaults to USDC",
}).argv;
async function setupLookupTable() {
    const resolvedArgv = await argv;
    const burnToken = new web3_js_1.PublicKey(resolvedArgv.burnToken);
    const txSigner = provider.wallet.publicKey;
    const txPayer = provider.wallet.payer;
    if (!txPayer) {
        throw new Error("Provider wallet does not have a keypair");
    }
    const eventAuthority = (0, web3_v1_1.findProgramAddress)("__event_authority", program.programId).publicKey;
    const state = (0, web3_v1_1.findProgramAddress)("state", program.programId).publicKey;
    const rentFund = (0, web3_v1_1.findProgramAddress)("rent_fund", program.programId).publicKey;
    const [minimumDeposit] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("minimum_deposit"), burnToken.toBuffer()], program.programId);
    const tokenMessengerMinterSenderAuthority = (0, web3_v1_1.findProgramAddress)("sender_authority", tokenMessengerMinterV2Program.programId).publicKey;
    const messageTransmitter = (0, web3_v1_1.findProgramAddress)("message_transmitter", messageTransmitterV2Program.programId).publicKey;
    const tokenMessenger = (0, web3_v1_1.findProgramAddress)("token_messenger", tokenMessengerMinterV2Program.programId).publicKey;
    const tokenMinter = (0, web3_v1_1.findProgramAddress)("token_minter", tokenMessengerMinterV2Program.programId).publicKey;
    const [localToken] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("local_token"), burnToken.toBuffer()], tokenMessengerMinterV2Program.programId);
    const cctpEventAuthority = (0, web3_v1_1.findProgramAddress)("__event_authority", tokenMessengerMinterV2Program.programId).publicKey;
    const tokenProgram = (await provider.connection.getAccountInfo(burnToken))?.owner;
    if (!tokenProgram)
        throw new Error("Burn token owner not found");
    if (!(tokenProgram.equals(spl_token_1.TOKEN_PROGRAM_ID) || tokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID)))
        throw new Error("Burn token is not a valid SPL token");
    const lookupAddresses = [
        state,
        burnToken,
        tokenMessengerMinterSenderAuthority,
        messageTransmitter,
        tokenMessenger,
        tokenMinter,
        localToken,
        cctpEventAuthority,
        messageTransmitterV2Program.programId,
        tokenMessengerMinterV2Program.programId,
        tokenProgram,
        web3_js_1.SystemProgram.programId,
        eventAuthority,
        rentFund,
        minimumDeposit,
    ];
    const [lookupTableInstruction, lookupTableAddress] = web3_js_1.AddressLookupTableProgram.createLookupTable({
        authority: txSigner,
        payer: txSigner,
        recentSlot: await provider.connection.getSlot(),
    });
    console.log(`Creating lookup table at ${lookupTableAddress}, containing addresses:`);
    console.table([
        { Property: "state", Value: state.toString() },
        { Property: "burnToken", Value: burnToken.toString() },
        { Property: "tokenMessengerMinterSenderAuthority", Value: tokenMessengerMinterSenderAuthority.toString() },
        { Property: "messageTransmitter", Value: messageTransmitter.toString() },
        { Property: "tokenMessenger", Value: tokenMessenger.toString() },
        { Property: "tokenMinter", Value: tokenMinter.toString() },
        { Property: "localToken", Value: localToken.toString() },
        { Property: "cctpEventAuthority", Value: cctpEventAuthority.toString() },
        { Property: "messageTransmitterV2ProgramId", Value: messageTransmitterV2Program.programId.toString() },
        { Property: "tokenMessengerMinterV2ProgramId", Value: tokenMessengerMinterV2Program.programId.toString() },
        { Property: "tokenProgram", Value: tokenProgram.toString() },
        { Property: "systemProgram", Value: web3_js_1.SystemProgram.programId.toString() },
        { Property: "eventAuthority", Value: eventAuthority.toString() },
        { Property: "rentFund", Value: rentFund.toString() },
        { Property: "minimumDeposit", Value: minimumDeposit.toString() },
    ]);
    const createTx = await (0, web3_js_1.sendAndConfirmTransaction)(provider.connection, new web3_js_1.Transaction().add(lookupTableInstruction), [txPayer], {
        commitment: "confirmed",
        skipPreflight: true,
    });
    console.log("Lookup table created successfully, transaction signature:", createTx);
    const extendInstruction = web3_js_1.AddressLookupTableProgram.extendLookupTable({
        lookupTable: lookupTableAddress,
        authority: txSigner,
        payer: txSigner,
        addresses: lookupAddresses,
    });
    const extendTx = await (0, web3_js_1.sendAndConfirmTransaction)(provider.connection, new web3_js_1.Transaction().add(extendInstruction), [txPayer], {
        commitment: "confirmed",
        skipPreflight: true,
    });
    console.log("Lookup table extended successfully, transaction signature:", extendTx);
    // Wait for slot to advance. ALTs only active after slot advance.
    const initialSlot = await provider.connection.getSlot();
    while ((await provider.connection.getSlot()) === initialSlot) {
        await new Promise((resolve) => setTimeout(resolve, 50));
    }
    const fetchedLookupTableAccount = (await provider.connection.getAddressLookupTable(lookupTableAddress)).value;
    if (fetchedLookupTableAccount === null)
        throw new Error("AddressLookupTableAccount not fetched");
}
setupLookupTable();
