import { __awaiter, __generator, __spreadArray } from "tslib";
import { appendTransactionMessageInstruction, appendTransactionMessageInstructions, assertIsTransactionWithBlockhashLifetime, assertIsTransactionWithinSizeLimit, compressTransactionMessageUsingAddressLookupTables as compressTxWithAlt, createTransactionMessage, getSignatureFromTransaction, pipe, sendAndConfirmTransactionFactory, setTransactionMessageFeePayerSigner, setTransactionMessageLifetimeUsingBlockhash, signTransactionMessageWithSigners, } from "@solana/kit";
import { fetchAddressLookupTable, findAddressLookupTablePda, getCreateLookupTableInstructionAsync, getExtendLookupTableInstruction, } from "@solana-program/address-lookup-table";
/**
 * Signs and sends a transaction.
 */
export var signAndSendTransaction = function (rpcClient_1, transactionMessage_1) {
    var args_1 = [];
    for (var _i = 2; _i < arguments.length; _i++) {
        args_1[_i - 2] = arguments[_i];
    }
    return __awaiter(void 0, __spreadArray([rpcClient_1, transactionMessage_1], args_1, true), void 0, function (rpcClient, transactionMessage, commitment) {
        var signedTransaction, signature;
        if (commitment === void 0) { commitment = "confirmed"; }
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, signTransactionMessageWithSigners(transactionMessage)];
                case 1:
                    signedTransaction = _a.sent();
                    assertIsTransactionWithBlockhashLifetime(signedTransaction);
                    assertIsTransactionWithinSizeLimit(signedTransaction);
                    signature = getSignatureFromTransaction(signedTransaction);
                    return [4 /*yield*/, sendAndConfirmTransactionFactory(rpcClient)(signedTransaction, {
                            commitment: commitment,
                        })];
                case 2:
                    _a.sent();
                    return [2 /*return*/, signature];
            }
        });
    });
};
export var createDefaultTransaction = function (rpcClient, signer) { return __awaiter(void 0, void 0, void 0, function () {
    var latestBlockhash;
    return __generator(this, function (_a) {
        switch (_a.label) {
            case 0: return [4 /*yield*/, rpcClient.rpc.getLatestBlockhash().send()];
            case 1:
                latestBlockhash = (_a.sent()).value;
                return [2 /*return*/, pipe(createTransactionMessage({ version: 0 }), function (tx) { return setTransactionMessageFeePayerSigner(signer, tx); }, function (tx) { return setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx); })];
        }
    });
}); };
/**
 * Sends a transaction with an Address Lookup Table.
 */
export function sendTransactionWithLookupTable(client, payer, instructions, addressesByLookupTableAddress) {
    return __awaiter(this, void 0, void 0, function () {
        var _a;
        var _this = this;
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    _a = pipe;
                    return [4 /*yield*/, createDefaultTransaction(client, payer)];
                case 1: return [2 /*return*/, _a.apply(void 0, [_b.sent(), function (tx) { return appendTransactionMessageInstructions(instructions, tx); },
                        function (tx) { return compressTxWithAlt(tx, addressesByLookupTableAddress); },
                        function (tx) { return signTransactionMessageWithSigners(tx); },
                        function (tx) { return __awaiter(_this, void 0, void 0, function () {
                            var signedTx;
                            return __generator(this, function (_a) {
                                switch (_a.label) {
                                    case 0: return [4 /*yield*/, tx];
                                    case 1:
                                        signedTx = _a.sent();
                                        assertIsTransactionWithBlockhashLifetime(signedTx);
                                        assertIsTransactionWithinSizeLimit(signedTx);
                                        return [4 /*yield*/, sendAndConfirmTransactionFactory(client)(signedTx, {
                                                commitment: "confirmed",
                                                skipPreflight: false,
                                            })];
                                    case 2:
                                        _a.sent();
                                        return [2 /*return*/, getSignatureFromTransaction(signedTx)];
                                }
                            });
                        }); }])];
            }
        });
    });
}
/**
 * Creates an Address Lookup Table.
 */
export function createLookupTable(client, authority) {
    return __awaiter(this, void 0, void 0, function () {
        var recentSlot, alt, createAltIx, _a;
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0: return [4 /*yield*/, client.rpc.getSlot({ commitment: "finalized" }).send()];
                case 1:
                    recentSlot = _b.sent();
                    return [4 /*yield*/, findAddressLookupTablePda({
                            authority: authority.address,
                            recentSlot: recentSlot,
                        })];
                case 2:
                    alt = (_b.sent())[0];
                    return [4 /*yield*/, getCreateLookupTableInstructionAsync({
                            authority: authority,
                            recentSlot: recentSlot,
                        })];
                case 3:
                    createAltIx = _b.sent();
                    _a = pipe;
                    return [4 /*yield*/, createDefaultTransaction(client, authority)];
                case 4: return [4 /*yield*/, _a.apply(void 0, [_b.sent(), function (tx) { return appendTransactionMessageInstruction(createAltIx, tx); },
                        function (tx) { return signAndSendTransaction(client, tx); }])];
                case 5:
                    _b.sent();
                    return [2 /*return*/, alt];
            }
        });
    });
}
/**
 * Extends an Address Lookup Table.
 */
export function extendLookupTable(client, authority, alt, addresses) {
    return __awaiter(this, void 0, void 0, function () {
        var extendAltIx, _a, altAccount, addressesByLookupTableAddress;
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    extendAltIx = getExtendLookupTableInstruction({
                        address: alt,
                        authority: authority,
                        payer: authority,
                        addresses: addresses,
                    });
                    _a = pipe;
                    return [4 /*yield*/, createDefaultTransaction(client, authority)];
                case 1: return [4 /*yield*/, _a.apply(void 0, [_b.sent(), function (tx) { return appendTransactionMessageInstruction(extendAltIx, tx); },
                        function (tx) { return signAndSendTransaction(client, tx); }])];
                case 2:
                    _b.sent();
                    return [4 /*yield*/, fetchAddressLookupTable(client.rpc, alt)];
                case 3:
                    altAccount = _b.sent();
                    addressesByLookupTableAddress = {};
                    addressesByLookupTableAddress[alt] = altAccount.data.addresses;
                    // Delay a second here to let lookup table warm up
                    return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 1000); })];
                case 4:
                    // Delay a second here to let lookup table warm up
                    _b.sent();
                    return [2 /*return*/, addressesByLookupTableAddress];
            }
        });
    });
}
//# sourceMappingURL=transactionUtils.js.map