"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createDefaultTransaction = exports.signAndSendTransaction = void 0;
exports.sendTransactionWithLookupTable = sendTransactionWithLookupTable;
exports.createLookupTable = createLookupTable;
exports.extendLookupTable = extendLookupTable;
const kit_1 = require("@solana/kit");
const address_lookup_table_1 = require("@solana-program/address-lookup-table");
/**
 * Signs and sends a transaction.
 */
const signAndSendTransaction = async (rpcClient, transactionMessage, commitment = "confirmed") => {
    const signedTransaction = await (0, kit_1.signTransactionMessageWithSigners)(transactionMessage);
    (0, kit_1.assertIsTransactionWithBlockhashLifetime)(signedTransaction);
    (0, kit_1.assertIsTransactionWithinSizeLimit)(signedTransaction);
    const signature = (0, kit_1.getSignatureFromTransaction)(signedTransaction);
    await (0, kit_1.sendAndConfirmTransactionFactory)(rpcClient)(signedTransaction, {
        commitment,
    });
    return signature;
};
exports.signAndSendTransaction = signAndSendTransaction;
const createDefaultTransaction = async (rpcClient, signer) => {
    const { value: latestBlockhash } = await rpcClient.rpc.getLatestBlockhash().send();
    return (0, kit_1.pipe)((0, kit_1.createTransactionMessage)({ version: 0 }), (tx) => (0, kit_1.setTransactionMessageFeePayerSigner)(signer, tx), (tx) => (0, kit_1.setTransactionMessageLifetimeUsingBlockhash)(latestBlockhash, tx));
};
exports.createDefaultTransaction = createDefaultTransaction;
/**
 * Sends a transaction with an Address Lookup Table.
 */
async function sendTransactionWithLookupTable(client, payer, instructions, addressesByLookupTableAddress) {
    return (0, kit_1.pipe)(await (0, exports.createDefaultTransaction)(client, payer), (tx) => (0, kit_1.appendTransactionMessageInstructions)(instructions, tx), (tx) => (0, kit_1.compressTransactionMessageUsingAddressLookupTables)(tx, addressesByLookupTableAddress), (tx) => (0, kit_1.signTransactionMessageWithSigners)(tx), async (tx) => {
        const signedTx = await tx;
        (0, kit_1.assertIsTransactionWithBlockhashLifetime)(signedTx);
        (0, kit_1.assertIsTransactionWithinSizeLimit)(signedTx);
        await (0, kit_1.sendAndConfirmTransactionFactory)(client)(signedTx, {
            commitment: "confirmed",
            skipPreflight: false,
        });
        return (0, kit_1.getSignatureFromTransaction)(signedTx);
    });
}
/**
 * Creates an Address Lookup Table.
 */
async function createLookupTable(client, authority) {
    const recentSlot = await client.rpc.getSlot({ commitment: "finalized" }).send();
    const [alt] = await (0, address_lookup_table_1.findAddressLookupTablePda)({
        authority: authority.address,
        recentSlot,
    });
    const createAltIx = await (0, address_lookup_table_1.getCreateLookupTableInstructionAsync)({
        authority,
        recentSlot,
    });
    await (0, kit_1.pipe)(await (0, exports.createDefaultTransaction)(client, authority), (tx) => (0, kit_1.appendTransactionMessageInstruction)(createAltIx, tx), (tx) => (0, exports.signAndSendTransaction)(client, tx));
    return alt;
}
/**
 * Extends an Address Lookup Table.
 */
async function extendLookupTable(client, authority, alt, addresses) {
    const extendAltIx = (0, address_lookup_table_1.getExtendLookupTableInstruction)({
        address: alt,
        authority,
        payer: authority,
        addresses,
    });
    await (0, kit_1.pipe)(await (0, exports.createDefaultTransaction)(client, authority), (tx) => (0, kit_1.appendTransactionMessageInstruction)(extendAltIx, tx), (tx) => (0, exports.signAndSendTransaction)(client, tx));
    const altAccount = await (0, address_lookup_table_1.fetchAddressLookupTable)(client.rpc, alt);
    const addressesByLookupTableAddress = {};
    addressesByLookupTableAddress[alt] = altAccount.data.addresses;
    // Delay a second here to let lookup table warm up
    await new Promise((resolve) => setTimeout(resolve, 1000));
    return addressesByLookupTableAddress;
}
