"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.finalizeCCTPV1Messages = exports.getCCTPV1ReceiveMessageTx = exports.getAccountMetasForTokenlessMessage = exports.hasCCTPV1MessageBeenProcessed = exports.getFillRelayDelegatePda = exports.getDepositNowDelegatePda = exports.getDepositDelegatePda = exports.getRelayDataHash = exports.getAssociatedTokenAddress = exports.createReceiveMessageInstruction = exports.createCloseFillPdaInstruction = exports.getSlowFillRequestTx = exports.createRequestSlowFillInstruction = exports.createDepositInstruction = exports.createFillInstruction = exports.getFillRelayTx = exports.createTokenAccountsInstruction = exports.fillRelayInstruction = exports.findFillEvent = exports.fillStatusArray = exports.relayFillStatus = exports.findDeposit = exports.getDepositIdAtBlock = exports.getFillDeadline = exports.getTimestampForSlot = exports.SLOT_DURATION_MS = void 0;
var tslib_1 = require("tslib");
var contracts_1 = require("@across-protocol/contracts");
var SvmSpoke_1 = require("@across-protocol/contracts/dist/src/svm/clients/SvmSpoke");
var web3_v1_1 = require("@across-protocol/contracts/dist/src/svm/web3-v1");
var conversionUtils_1 = require("@across-protocol/contracts/dist/src/svm/web3-v1/conversionUtils");
var system_1 = require("@solana-program/system");
var token_1 = require("@solana-program/token");
var kit_1 = require("@solana/kit");
var assert_1 = tslib_1.__importDefault(require("assert"));
var utils_1 = require("ethers/lib/utils");
var constants_1 = require("../../constants");
var interfaces_1 = require("../../interfaces");
var utils_2 = require("../../utils");
var _1 = require("./");
var provider_1 = require("./provider");
var types_1 = require("./types");
var utils_3 = require("./utils");
exports.SLOT_DURATION_MS = 400;
function getTimestampForSlot(provider, slotNumber) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var _timestamp, err_1, code, timestamp;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    _a.trys.push([0, 2, , 3]);
                    return [4, provider.getBlockTime(slotNumber).send()];
                case 1:
                    _timestamp = _a.sent();
                    return [3, 3];
                case 2:
                    err_1 = _a.sent();
                    if (!(0, provider_1.isSolanaError)(err_1)) {
                        throw err_1;
                    }
                    code = err_1.context.__code;
                    if ([provider_1.SVM_NO_BLOCK_AT_SLOT].includes(code)) {
                        return [2, undefined];
                    }
                    throw err_1;
                case 3:
                    timestamp = Number(_timestamp);
                    (0, assert_1.default)(BigInt(timestamp) === _timestamp, "Unexpected SVM block timestamp: ".concat(_timestamp));
                    return [2, timestamp];
            }
        });
    });
}
exports.getTimestampForSlot = getTimestampForSlot;
function getFillDeadline(provider, statePda) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var state;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4, (0, SvmSpoke_1.fetchState)(provider, statePda)];
                case 1:
                    state = _a.sent();
                    return [2, state.data.fillDeadlineBuffer];
            }
        });
    });
}
exports.getFillDeadline = getFillDeadline;
function getDepositIdAtBlock(_contract, _blockTag) {
    throw new Error("getDepositIdAtBlock: not implemented");
}
exports.getDepositIdAtBlock = getDepositIdAtBlock;
function findDeposit(eventClient, depositId, slot, secondsLookback) {
    var _a;
    if (secondsLookback === void 0) { secondsLookback = 2 * 24 * 60 * 60; }
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var provider, currentSlot, endSlot, slotsInElapsed, startSlot, depositEvent, unwrappedDepositEvent, destinationChainId;
        return tslib_1.__generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    if ((0, utils_2.isUnsafeDepositId)(depositId)) {
                        throw new Error("Cannot binary search for depositId ".concat(depositId));
                    }
                    provider = eventClient.getRpc();
                    return [4, (0, utils_3.getNearestSlotTime)(provider)];
                case 1:
                    currentSlot = (_b.sent()).slot;
                    endSlot = slot !== undefined ? BigInt(Math.min(Number(slot), Number(currentSlot))) : currentSlot;
                    slotsInElapsed = BigInt(Math.round((secondsLookback * 1000) / exports.SLOT_DURATION_MS));
                    startSlot = endSlot - slotsInElapsed;
                    return [4, eventClient.queryEvents("FundsDeposited", startSlot, endSlot)];
                case 2:
                    depositEvent = (_a = (_b.sent())) === null || _a === void 0 ? void 0 : _a.find(function (event) {
                        return depositId.eq(event.data.depositId);
                    });
                    if (!depositEvent) {
                        return [2, undefined];
                    }
                    unwrappedDepositEvent = (0, _1.unwrapEventData)(depositEvent.data, ["depositId", "outputAmount"]);
                    destinationChainId = unwrappedDepositEvent.destinationChainId;
                    return [2, tslib_1.__assign(tslib_1.__assign({ txnRef: depositEvent.signature.toString(), blockNumber: Number(depositEvent.slot), txnIndex: 0, logIndex: 0 }, unwrappedDepositEvent), { depositor: (0, utils_2.toAddressType)(unwrappedDepositEvent.depositor, constants_1.CHAIN_IDs.SOLANA), recipient: (0, utils_2.toAddressType)(unwrappedDepositEvent.recipient, destinationChainId), inputToken: (0, utils_2.toAddressType)(unwrappedDepositEvent.inputToken, constants_1.CHAIN_IDs.SOLANA), outputToken: (0, utils_2.toAddressType)(unwrappedDepositEvent.outputToken, destinationChainId), exclusiveRelayer: (0, utils_2.toAddressType)(unwrappedDepositEvent.exclusiveRelayer, destinationChainId) })];
            }
        });
    });
}
exports.findDeposit = findDeposit;
function relayFillStatus(programId, relayData, destinationChainId, svmEventsClient, atHeight) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var provider, fillStatusPda, toSlot, commitment, _a, fillStatusAccount, _b, currentSlot, timestamp, decodedAccountData;
        return tslib_1.__generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    (0, assert_1.default)((0, utils_2.chainIsSvm)(destinationChainId), "Destination chain must be an SVM chain");
                    provider = svmEventsClient.getRpc();
                    return [4, (0, _1.getFillStatusPda)(programId, relayData, destinationChainId)];
                case 1:
                    fillStatusPda = _c.sent();
                    toSlot = BigInt(atHeight !== null && atHeight !== void 0 ? atHeight : 0);
                    if (!(atHeight === undefined)) return [3, 3];
                    commitment = "confirmed";
                    return [4, Promise.all([
                            (0, kit_1.fetchEncodedAccount)(provider, fillStatusPda, { commitment: commitment }),
                            (0, utils_3.getNearestSlotTime)(provider, { commitment: commitment }),
                        ])];
                case 2:
                    _a = _c.sent(), fillStatusAccount = _a[0], _b = _a[1], currentSlot = _b.slot, timestamp = _b.timestamp;
                    toSlot = currentSlot;
                    if (fillStatusAccount.exists) {
                        decodedAccountData = (0, SvmSpoke_1.decodeFillStatusAccount)(fillStatusAccount);
                        return [2, decodedAccountData.data.status];
                    }
                    else if (timestamp < relayData.fillDeadline) {
                        return [2, interfaces_1.FillStatus.Unfilled];
                    }
                    _c.label = 3;
                case 3: return [2, resolveFillStatusFromPdaEvents(fillStatusPda, toSlot, svmEventsClient)];
            }
        });
    });
}
exports.relayFillStatus = relayFillStatus;
function fillStatusArray(programId, relayData, destinationChainId, svmEventsClient, atHeight, logger) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var provider, chunkSize, chunkedRelayData, fillStatusPdas, fillStatuses, _a, missingStatuses, missingChunked, missingResults, toSlot, _b, _i, missingChunked_1, chunk_1, chunkResults;
        var _this = this;
        return tslib_1.__generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    (0, assert_1.default)((0, utils_2.chainIsSvm)(destinationChainId), "Destination chain must be an SVM chain");
                    provider = svmEventsClient.getRpc();
                    chunkSize = 100;
                    chunkedRelayData = (0, utils_2.chunk)(relayData, chunkSize);
                    return [4, Promise.all(chunkedRelayData.map(function (relayDataChunk) {
                            return Promise.all(relayDataChunk.map(function (relayData) { return (0, _1.getFillStatusPda)(programId, relayData, destinationChainId); }));
                        }))];
                case 1:
                    fillStatusPdas = (_c.sent()).flat();
                    if (atHeight !== undefined && logger) {
                        logger.warn({
                            at: "SvmSpokeUtils#fillStatusArray",
                            message: "Querying specific slots for large arrays is slow. For current status, omit 'atHeight' param to use latest confirmed slot instead.",
                        });
                    }
                    if (!(atHeight === undefined)) return [3, 3];
                    return [4, fetchBatchFillStatusFromPdaAccounts(provider, fillStatusPdas, relayData)];
                case 2:
                    _a = _c.sent();
                    return [3, 4];
                case 3:
                    _a = new Array(relayData.length).fill(undefined);
                    _c.label = 4;
                case 4:
                    fillStatuses = _a;
                    missingStatuses = fillStatuses.reduce(function (acc, status, index) {
                        if (status === undefined) {
                            acc.push(index);
                        }
                        return acc;
                    }, []);
                    missingChunked = (0, utils_2.chunk)(missingStatuses, chunkSize);
                    missingResults = [];
                    if (!atHeight) return [3, 5];
                    _b = BigInt(atHeight);
                    return [3, 7];
                case 5: return [4, (0, utils_3.getNearestSlotTime)(provider)];
                case 6:
                    _b = (_c.sent()).slot;
                    _c.label = 7;
                case 7:
                    toSlot = _b;
                    _i = 0, missingChunked_1 = missingChunked;
                    _c.label = 8;
                case 8:
                    if (!(_i < missingChunked_1.length)) return [3, 11];
                    chunk_1 = missingChunked_1[_i];
                    return [4, Promise.all(chunk_1.map(function (missingIndex) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
                            var _a;
                            return tslib_1.__generator(this, function (_b) {
                                switch (_b.label) {
                                    case 0:
                                        _a = {
                                            index: missingIndex
                                        };
                                        return [4, resolveFillStatusFromPdaEvents(fillStatusPdas[missingIndex], toSlot, svmEventsClient)];
                                    case 1: return [2, (_a.fillStatus = _b.sent(),
                                            _a)];
                                }
                            });
                        }); }))];
                case 9:
                    chunkResults = _c.sent();
                    missingResults.push.apply(missingResults, chunkResults);
                    _c.label = 10;
                case 10:
                    _i++;
                    return [3, 8];
                case 11:
                    missingResults.forEach(function (_a) {
                        var index = _a.index, fillStatus = _a.fillStatus;
                        fillStatuses[index] = fillStatus;
                    });
                    return [2, fillStatuses];
            }
        });
    });
}
exports.fillStatusArray = fillStatusArray;
function findFillEvent(relayData, destinationChainId, svmEventsClient, fromSlot, toSlot) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var _a, _b, programId, fillStatusPda, fillEvents, rawFillEvent, eventData, originChainId, parsedFillEvent;
        return tslib_1.__generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    (0, assert_1.default)((0, utils_2.chainIsSvm)(destinationChainId), "Destination chain must be an SVM chain");
                    if (!(toSlot !== null && toSlot !== void 0)) return [3, 1];
                    _a = toSlot;
                    return [3, 3];
                case 1:
                    _b = Number;
                    return [4, (0, utils_3.getNearestSlotTime)(svmEventsClient.getRpc())];
                case 2:
                    _a = (toSlot = _b.apply(void 0, [(_c.sent()).slot]));
                    _c.label = 3;
                case 3:
                    _a;
                    programId = svmEventsClient.getProgramAddress();
                    return [4, (0, _1.getFillStatusPda)(programId, relayData, destinationChainId)];
                case 4:
                    fillStatusPda = _c.sent();
                    return [4, svmEventsClient.queryDerivedAddressEvents(types_1.SVMEventNames.FilledRelay, fillStatusPda, BigInt(fromSlot), BigInt(toSlot), { limit: 10 })];
                case 5:
                    fillEvents = _c.sent();
                    (0, assert_1.default)(fillEvents.length <= 1, "Expected at most one fill event for ".concat(fillStatusPda, ", got ").concat(fillEvents.length));
                    if (fillEvents.length > 0) {
                        rawFillEvent = fillEvents[0];
                        eventData = (0, _1.unwrapEventData)(rawFillEvent.data, ["depositId", "inputAmount"]);
                        originChainId = eventData.originChainId;
                        parsedFillEvent = tslib_1.__assign(tslib_1.__assign({}, eventData), { transactionHash: rawFillEvent.signature, blockNumber: Number(rawFillEvent.slot), transactionIndex: 0, logIndex: 0, destinationChainId: destinationChainId, inputToken: (0, utils_2.toAddressType)(eventData.inputToken, originChainId), outputToken: (0, utils_2.toAddressType)(eventData.outputToken, destinationChainId), relayer: (0, utils_2.toAddressType)(eventData.relayer, destinationChainId), exclusiveRelayer: (0, utils_2.toAddressType)(eventData.exclusiveRelayer, destinationChainId), depositor: (0, utils_2.toAddressType)(eventData.depositor, originChainId), recipient: (0, utils_2.toAddressType)(eventData.recipient, destinationChainId), relayExecutionInfo: tslib_1.__assign(tslib_1.__assign({}, eventData.relayExecutionInfo), { updatedRecipient: eventData.relayExecutionInfo.updatedRecipient }) });
                        return [2, parsedFillEvent];
                    }
                    return [2, undefined];
            }
        });
    });
}
exports.findFillEvent = findFillEvent;
function fillRelayInstruction(spokePool, relayData, signer, recipientTokenAccount, repaymentAddress, repaymentChainId) {
    if (repaymentAddress === void 0) { repaymentAddress = utils_2.SvmAddress.from(signer.address); }
    if (repaymentChainId === void 0) { repaymentChainId = relayData.destinationChainId; }
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var program, _relayDataHash, relayDataHash, relayer, relayerTokenAccount, _a, statePda, fillStatusPda, eventAuthority, depositIdBuffer, shortenedBuffer, delegatePda, _b, recipient, outputToken, exclusiveRelayer, depositor, inputToken;
        return tslib_1.__generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    program = (0, _1.toAddress)(spokePool);
                    (0, assert_1.default)(repaymentAddress.isValidOn(repaymentChainId), "Invalid repayment address for chain ".concat(repaymentChainId, ": ").concat(repaymentAddress.toNative(), "."));
                    _relayDataHash = getRelayDataHash(relayData, relayData.destinationChainId);
                    relayDataHash = new Uint8Array(Buffer.from(_relayDataHash.slice(2), "hex"));
                    relayer = utils_2.SvmAddress.from(signer.address);
                    return [4, getAssociatedTokenAddress(relayer, relayData.outputToken)];
                case 1:
                    relayerTokenAccount = _c.sent();
                    return [4, Promise.all([
                            (0, _1.getStatePda)(program),
                            (0, _1.getFillStatusPda)(program, relayData, relayData.destinationChainId),
                            (0, _1.getEventAuthority)(program),
                        ])];
                case 2:
                    _a = _c.sent(), statePda = _a[0], fillStatusPda = _a[1], eventAuthority = _a[2];
                    depositIdBuffer = new Uint8Array(32);
                    shortenedBuffer = new Uint8Array(Buffer.from(relayData.depositId.toHexString().slice(2), "hex"));
                    depositIdBuffer.set(shortenedBuffer, 32 - shortenedBuffer.length);
                    return [4, getFillRelayDelegatePda(relayDataHash, BigInt(repaymentChainId), (0, _1.toAddress)(relayer), program)];
                case 3:
                    delegatePda = _c.sent();
                    _b = [
                        relayData.recipient,
                        relayData.outputToken,
                        relayData.exclusiveRelayer,
                        relayData.depositor,
                        relayData.inputToken,
                    ].map(_1.toAddress), recipient = _b[0], outputToken = _b[1], exclusiveRelayer = _b[2], depositor = _b[3], inputToken = _b[4];
                    return [2, contracts_1.SvmSpokeClient.getFillRelayInstruction({
                            signer: signer,
                            state: statePda,
                            delegate: (0, _1.toAddress)(utils_2.SvmAddress.from(delegatePda.toString())),
                            mint: outputToken,
                            relayerTokenAccount: relayerTokenAccount,
                            recipientTokenAccount: recipientTokenAccount,
                            fillStatus: fillStatusPda,
                            eventAuthority: eventAuthority,
                            program: program,
                            relayHash: relayDataHash,
                            relayData: (0, kit_1.some)({
                                depositor: depositor,
                                recipient: recipient,
                                exclusiveRelayer: exclusiveRelayer,
                                inputToken: inputToken,
                                outputToken: outputToken,
                                inputAmount: (0, _1.bigToU8a32)(relayData.inputAmount.toBigInt()),
                                outputAmount: relayData.outputAmount.toBigInt(),
                                originChainId: BigInt(relayData.originChainId),
                                fillDeadline: relayData.fillDeadline,
                                exclusivityDeadline: relayData.exclusivityDeadline,
                                depositId: depositIdBuffer,
                                message: new Uint8Array(Buffer.from(relayData.message.slice(2), "hex")),
                            }),
                            repaymentChainId: (0, kit_1.some)(BigInt(repaymentChainId)),
                            repaymentAddress: (0, _1.toAddress)(repaymentAddress),
                        })];
            }
        });
    });
}
exports.fillRelayInstruction = fillRelayInstruction;
function createTokenAccountsInstruction(mint, relayer) {
    return contracts_1.SvmSpokeClient.getCreateTokenAccountsInstruction({
        signer: relayer,
        mint: (0, _1.toAddress)(mint),
    });
}
exports.createTokenAccountsInstruction = createTokenAccountsInstruction;
function getFillRelayTx(spokePoolAddr, solanaClient, relayData, signer, repaymentChainId, repaymentAddress) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var depositor, recipient, inputToken, outputToken, exclusiveRelayer, destinationChainId, program, _relayDataHash, relayDataHash, _a, state, delegate, mint, mintInfo, _b, recipientAta, relayerAta, fillStatus, eventAuthority, svmRelayData, fillInput;
        return tslib_1.__generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    depositor = relayData.depositor, recipient = relayData.recipient, inputToken = relayData.inputToken, outputToken = relayData.outputToken, exclusiveRelayer = relayData.exclusiveRelayer, destinationChainId = relayData.destinationChainId;
                    (0, assert_1.default)(repaymentAddress.isValidOn(repaymentChainId), "getFillRelayTx: repayment address ".concat(repaymentAddress, " not valid on chain ").concat(repaymentChainId, ")"));
                    program = (0, _1.toAddress)(spokePoolAddr);
                    _relayDataHash = getRelayDataHash(relayData, destinationChainId);
                    relayDataHash = new Uint8Array(Buffer.from(_relayDataHash.slice(2), "hex"));
                    return [4, Promise.all([
                            (0, _1.getStatePda)(program),
                            getFillRelayDelegatePda(relayDataHash, BigInt(repaymentChainId), (0, _1.toAddress)(repaymentAddress), program),
                        ])];
                case 1:
                    _a = _c.sent(), state = _a[0], delegate = _a[1];
                    mint = (0, _1.toAddress)(outputToken);
                    return [4, (0, token_1.fetchMint)(solanaClient, mint)];
                case 2:
                    mintInfo = _c.sent();
                    return [4, Promise.all([
                            getAssociatedTokenAddress(recipient, outputToken, mintInfo.programAddress),
                            getAssociatedTokenAddress(utils_2.SvmAddress.from(signer.address), outputToken, mintInfo.programAddress),
                            (0, _1.getFillStatusPda)(program, relayData, destinationChainId),
                            (0, _1.getEventAuthority)(program),
                        ])];
                case 3:
                    _b = _c.sent(), recipientAta = _b[0], relayerAta = _b[1], fillStatus = _b[2], eventAuthority = _b[3];
                    svmRelayData = {
                        depositor: (0, _1.toAddress)(depositor),
                        recipient: (0, _1.toAddress)(recipient),
                        exclusiveRelayer: (0, _1.toAddress)(exclusiveRelayer),
                        inputToken: (0, _1.toAddress)(inputToken),
                        outputToken: mint,
                        inputAmount: (0, _1.bigToU8a32)(relayData.inputAmount.toBigInt()),
                        outputAmount: relayData.outputAmount.toBigInt(),
                        originChainId: relayData.originChainId,
                        depositId: new Uint8Array((0, conversionUtils_1.intToU8Array32)(relayData.depositId.toNumber())),
                        fillDeadline: relayData.fillDeadline,
                        exclusivityDeadline: relayData.exclusivityDeadline,
                        message: new Uint8Array(Buffer.from(relayData.message, "hex")),
                    };
                    fillInput = {
                        signer: signer,
                        state: state,
                        delegate: delegate,
                        mint: mint,
                        relayerTokenAccount: relayerAta,
                        recipientTokenAccount: recipientAta,
                        fillStatus: fillStatus,
                        tokenProgram: mintInfo.programAddress,
                        associatedTokenProgram: token_1.ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
                        systemProgram: system_1.SYSTEM_PROGRAM_ADDRESS,
                        eventAuthority: eventAuthority,
                        program: program,
                        relayHash: relayDataHash,
                        relayData: svmRelayData,
                        repaymentChainId: BigInt(repaymentChainId),
                        repaymentAddress: (0, _1.toAddress)(repaymentAddress),
                    };
                    return [2, (0, exports.createFillInstruction)(signer, solanaClient, fillInput, mintInfo.data.decimals, true)];
            }
        });
    });
}
exports.getFillRelayTx = getFillRelayTx;
var createFillInstruction = function (signer, solanaClient, fillInput, tokenDecimals, createRecipientAtaIfNeeded) {
    if (createRecipientAtaIfNeeded === void 0) { createRecipientAtaIfNeeded = true; }
    return tslib_1.__awaiter(void 0, void 0, void 0, function () {
        var mintInfo, approveIx, getCreateAssociatedTokenIdempotentIx, createFillIx, _a;
        return tslib_1.__generator(this, function (_b) {
            switch (_b.label) {
                case 0: return [4, (0, token_1.fetchMint)(solanaClient, fillInput.mint)];
                case 1:
                    mintInfo = _b.sent();
                    approveIx = (0, token_1.getApproveCheckedInstruction)({
                        source: fillInput.relayerTokenAccount,
                        mint: fillInput.mint,
                        delegate: fillInput.delegate,
                        owner: fillInput.signer,
                        amount: fillInput.relayData.outputAmount,
                        decimals: tokenDecimals,
                    }, {
                        programAddress: mintInfo.programAddress,
                    });
                    getCreateAssociatedTokenIdempotentIx = function () {
                        return (0, token_1.getCreateAssociatedTokenIdempotentInstruction)({
                            payer: signer,
                            owner: fillInput.relayData.recipient,
                            mint: fillInput.mint,
                            ata: fillInput.recipientTokenAccount,
                            systemProgram: system_1.SYSTEM_PROGRAM_ADDRESS,
                            tokenProgram: fillInput.tokenProgram,
                        });
                    };
                    createFillIx = contracts_1.SvmSpokeClient.getFillRelayInstruction(fillInput);
                    _a = kit_1.pipe;
                    return [4, (0, _1.createDefaultTransaction)(solanaClient, signer)];
                case 2: return [2, _a.apply(void 0, [_b.sent(), function (tx) {
                            return createRecipientAtaIfNeeded ? (0, kit_1.appendTransactionMessageInstruction)(getCreateAssociatedTokenIdempotentIx(), tx) : tx;
                        },
                        function (tx) { return (0, kit_1.appendTransactionMessageInstruction)(approveIx, tx); },
                        function (tx) { return (0, kit_1.appendTransactionMessageInstruction)(createFillIx, tx); }])];
            }
        });
    });
};
exports.createFillInstruction = createFillInstruction;
var createDepositInstruction = function (signer, solanaClient, depositInput, tokenDecimals, createVaultAtaIfNeeded) {
    if (createVaultAtaIfNeeded === void 0) { createVaultAtaIfNeeded = true; }
    return tslib_1.__awaiter(void 0, void 0, void 0, function () {
        var getCreateAssociatedTokenIdempotentIx, mintInfo, approveIx, depositIx, _a;
        return tslib_1.__generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    getCreateAssociatedTokenIdempotentIx = function () {
                        return (0, token_1.getCreateAssociatedTokenIdempotentInstruction)({
                            payer: signer,
                            owner: depositInput.state,
                            mint: depositInput.mint,
                            ata: depositInput.vault,
                            systemProgram: depositInput.systemProgram,
                            tokenProgram: depositInput.tokenProgram,
                        });
                    };
                    return [4, (0, token_1.fetchMint)(solanaClient, depositInput.mint)];
                case 1:
                    mintInfo = _b.sent();
                    approveIx = (0, token_1.getApproveCheckedInstruction)({
                        source: depositInput.depositorTokenAccount,
                        mint: depositInput.mint,
                        delegate: depositInput.delegate,
                        owner: depositInput.depositor,
                        amount: depositInput.inputAmount,
                        decimals: tokenDecimals,
                    }, {
                        programAddress: mintInfo.programAddress,
                    });
                    depositIx = contracts_1.SvmSpokeClient.getDepositInstruction(depositInput);
                    _a = kit_1.pipe;
                    return [4, (0, _1.createDefaultTransaction)(solanaClient, signer)];
                case 2: return [2, _a.apply(void 0, [_b.sent(), function (tx) {
                            return createVaultAtaIfNeeded ? (0, kit_1.appendTransactionMessageInstruction)(getCreateAssociatedTokenIdempotentIx(), tx) : tx;
                        },
                        function (tx) { return (0, kit_1.appendTransactionMessageInstruction)(approveIx, tx); },
                        function (tx) { return (0, kit_1.appendTransactionMessageInstruction)(depositIx, tx); }])];
            }
        });
    });
};
exports.createDepositInstruction = createDepositInstruction;
var createRequestSlowFillInstruction = function (signer, solanaClient, requestSlowFillInput) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
    var requestSlowFillIx, _a;
    return tslib_1.__generator(this, function (_b) {
        switch (_b.label) {
            case 0:
                requestSlowFillIx = contracts_1.SvmSpokeClient.getRequestSlowFillInstruction(requestSlowFillInput);
                _a = kit_1.pipe;
                return [4, (0, _1.createDefaultTransaction)(solanaClient, signer)];
            case 1: return [2, _a.apply(void 0, [_b.sent(), function (tx) {
                        return (0, kit_1.appendTransactionMessageInstruction)(requestSlowFillIx, tx);
                    }])];
        }
    });
}); };
exports.createRequestSlowFillInstruction = createRequestSlowFillInstruction;
function getSlowFillRequestTx(spokePoolAddr, solanaClient, relayData, signer) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var depositor, recipient, inputToken, outputToken, exclusiveRelayer, destinationChainId, originChainId, depositId, fillDeadline, exclusivityDeadline, message, program, relayDataHash, _a, state, fillStatus, eventAuthority, depositIdBuffer, shortenedBuffer, relayDataInput, requestSlowFillInput;
        return tslib_1.__generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    depositor = relayData.depositor, recipient = relayData.recipient, inputToken = relayData.inputToken, outputToken = relayData.outputToken, exclusiveRelayer = relayData.exclusiveRelayer, destinationChainId = relayData.destinationChainId, originChainId = relayData.originChainId, depositId = relayData.depositId, fillDeadline = relayData.fillDeadline, exclusivityDeadline = relayData.exclusivityDeadline, message = relayData.message;
                    program = (0, _1.toAddress)(spokePoolAddr);
                    relayDataHash = getRelayDataHash(relayData, destinationChainId);
                    return [4, Promise.all([
                            (0, _1.getStatePda)(program),
                            (0, _1.getFillStatusPda)(program, relayData, destinationChainId),
                            (0, _1.getEventAuthority)(program),
                        ])];
                case 1:
                    _a = _b.sent(), state = _a[0], fillStatus = _a[1], eventAuthority = _a[2];
                    depositIdBuffer = new Uint8Array(32);
                    shortenedBuffer = (0, utils_1.arrayify)(depositId.toHexString());
                    depositIdBuffer.set(shortenedBuffer, 32 - shortenedBuffer.length);
                    relayDataInput = {
                        depositor: (0, _1.toAddress)(depositor),
                        recipient: (0, _1.toAddress)(recipient),
                        exclusiveRelayer: (0, _1.toAddress)(exclusiveRelayer),
                        inputToken: (0, _1.toAddress)(inputToken),
                        outputToken: (0, _1.toAddress)(outputToken),
                        inputAmount: (0, _1.bigToU8a32)(relayData.inputAmount.toBigInt()),
                        outputAmount: relayData.outputAmount.toBigInt(),
                        originChainId: BigInt(originChainId),
                        depositId: depositIdBuffer,
                        fillDeadline: fillDeadline,
                        exclusivityDeadline: exclusivityDeadline,
                        message: (0, utils_1.arrayify)(message),
                    };
                    requestSlowFillInput = {
                        signer: signer,
                        state: state,
                        fillStatus: fillStatus,
                        eventAuthority: eventAuthority,
                        program: program,
                        relayHash: (0, utils_1.arrayify)(relayDataHash),
                        relayData: relayDataInput,
                        systemProgram: system_1.SYSTEM_PROGRAM_ADDRESS,
                    };
                    return [2, (0, exports.createRequestSlowFillInstruction)(signer, solanaClient, requestSlowFillInput)];
            }
        });
    });
}
exports.getSlowFillRequestTx = getSlowFillRequestTx;
var createCloseFillPdaInstruction = function (signer, solanaClient, fillStatusPda) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
    var closeFillPdaIx, _a, _b, _c;
    var _d;
    return tslib_1.__generator(this, function (_e) {
        switch (_e.label) {
            case 0:
                _b = (_a = contracts_1.SvmSpokeClient).getCloseFillPdaInstruction;
                _d = {
                    signer: signer
                };
                return [4, (0, _1.getStatePda)(contracts_1.SvmSpokeClient.SVM_SPOKE_PROGRAM_ADDRESS)];
            case 1:
                closeFillPdaIx = _b.apply(_a, [(_d.state = _e.sent(),
                        _d.fillStatus = fillStatusPda,
                        _d)]);
                _c = kit_1.pipe;
                return [4, (0, _1.createDefaultTransaction)(solanaClient, signer)];
            case 2: return [2, _c.apply(void 0, [_e.sent(), function (tx) {
                        return (0, kit_1.appendTransactionMessageInstruction)(closeFillPdaIx, tx);
                    }])];
        }
    });
}); };
exports.createCloseFillPdaInstruction = createCloseFillPdaInstruction;
var createReceiveMessageInstruction = function (signer, solanaClient, input, remainingAccounts) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
    var receiveMessageIx, _a;
    var _b;
    return tslib_1.__generator(this, function (_c) {
        switch (_c.label) {
            case 0:
                receiveMessageIx = contracts_1.MessageTransmitterClient.getReceiveMessageInstruction(input);
                (_b = receiveMessageIx.accounts).push.apply(_b, remainingAccounts);
                _a = kit_1.pipe;
                return [4, (0, _1.createDefaultTransaction)(solanaClient, signer)];
            case 1: return [2, _a.apply(void 0, [_c.sent(), function (tx) {
                        return (0, kit_1.appendTransactionMessageInstruction)(receiveMessageIx, tx);
                    }])];
        }
    });
}); };
exports.createReceiveMessageInstruction = createReceiveMessageInstruction;
function getAssociatedTokenAddress(owner, mint, tokenProgramId) {
    if (tokenProgramId === void 0) { tokenProgramId = token_1.TOKEN_PROGRAM_ADDRESS; }
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var encoder, associatedToken;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    encoder = (0, kit_1.getAddressEncoder)();
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: token_1.ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
                            seeds: [encoder.encode((0, _1.toAddress)(owner)), encoder.encode(tokenProgramId), encoder.encode((0, _1.toAddress)(mint))],
                        })];
                case 1:
                    associatedToken = (_a.sent())[0];
                    return [2, associatedToken];
            }
        });
    });
}
exports.getAssociatedTokenAddress = getAssociatedTokenAddress;
function getRelayDataHash(relayData, destinationChainId) {
    var addressEncoder = (0, kit_1.getAddressEncoder)();
    var uint64Encoder = (0, kit_1.getU64Encoder)();
    var uint32Encoder = (0, kit_1.getU32Encoder)();
    (0, assert_1.default)(relayData.message.startsWith("0x"), "Message must be a hex string");
    var encodeAddress = function (data) { return Uint8Array.from(addressEncoder.encode((0, _1.toAddress)(data))); };
    var contentToHash = Buffer.concat([
        encodeAddress(relayData.depositor),
        encodeAddress(relayData.recipient),
        encodeAddress(relayData.exclusiveRelayer),
        encodeAddress(relayData.inputToken),
        encodeAddress(relayData.outputToken),
        (0, utils_1.arrayify)((0, utils_1.hexZeroPad)((0, utils_1.hexlify)(relayData.inputAmount), 32)),
        Uint8Array.from(uint64Encoder.encode(BigInt(relayData.outputAmount.toString()))),
        Uint8Array.from(uint64Encoder.encode(BigInt(relayData.originChainId.toString()))),
        (0, utils_1.arrayify)((0, utils_1.hexZeroPad)((0, utils_1.hexlify)(relayData.depositId), 32)),
        Uint8Array.from(uint32Encoder.encode(relayData.fillDeadline)),
        Uint8Array.from(uint32Encoder.encode(relayData.exclusivityDeadline)),
        (0, web3_v1_1.hashNonEmptyMessage)(Buffer.from((0, utils_1.arrayify)(relayData.message))),
        Uint8Array.from(uint64Encoder.encode(BigInt(destinationChainId))),
    ]);
    return (0, utils_2.keccak256)(contentToHash);
}
exports.getRelayDataHash = getRelayDataHash;
function resolveFillStatusFromPdaEvents(fillStatusPda, toSlot, svmEventsClient) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var eventsToQuery, relevantEvents, fillStatusEvent;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    eventsToQuery = [types_1.SVMEventNames.FilledRelay, types_1.SVMEventNames.RequestedSlowFill];
                    return [4, Promise.all(eventsToQuery.map(function (eventName) {
                            return svmEventsClient.queryDerivedAddressEvents(eventName, fillStatusPda, undefined, toSlot, { limit: 10 });
                        }))];
                case 1:
                    relevantEvents = (_a.sent()).flat();
                    if (relevantEvents.length === 0) {
                        return [2, interfaces_1.FillStatus.Unfilled];
                    }
                    relevantEvents.sort(function (a, b) { return Number(a.slot - b.slot); });
                    fillStatusEvent = relevantEvents.pop();
                    switch (fillStatusEvent.name) {
                        case types_1.SVMEventNames.FilledRelay:
                            return [2, interfaces_1.FillStatus.Filled];
                        case types_1.SVMEventNames.RequestedSlowFill:
                            return [2, interfaces_1.FillStatus.RequestedSlowFill];
                        default:
                            throw new Error("Unexpected event name: ".concat(fillStatusEvent.name));
                    }
                    return [2];
            }
        });
    });
}
function fetchBatchFillStatusFromPdaAccounts(provider, fillStatusPdas, relayDataArray) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var chunkSize, commitment, _a, pdaAccounts, timestamp, fillStatuses;
        return tslib_1.__generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    chunkSize = 100;
                    commitment = "confirmed";
                    return [4, Promise.all([
                            Promise.all((0, utils_2.chunk)(fillStatusPdas, chunkSize).map(function (chunk) { return (0, kit_1.fetchEncodedAccounts)(provider, chunk, { commitment: commitment }); })),
                            (0, utils_3.getNearestSlotTime)(provider, { commitment: commitment }),
                        ])];
                case 1:
                    _a = _b.sent(), pdaAccounts = _a[0], timestamp = _a[1].timestamp;
                    fillStatuses = pdaAccounts.flat().map(function (account, index) {
                        if (account.exists) {
                            var decodedAccount = (0, SvmSpoke_1.decodeFillStatusAccount)(account);
                            return decodedAccount.data.status;
                        }
                        if (timestamp < relayDataArray[index].fillDeadline) {
                            return interfaces_1.FillStatus.Unfilled;
                        }
                        return undefined;
                    });
                    return [2, fillStatuses];
            }
        });
    });
}
function getDepositDelegatePda(depositData, programId) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var addrEnc, u64, u32, parts, seedHash, pda;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    addrEnc = (0, kit_1.getAddressEncoder)();
                    u64 = (0, kit_1.getU64Encoder)();
                    u32 = (0, kit_1.getU32Encoder)();
                    parts = [
                        Uint8Array.from(addrEnc.encode(depositData.depositor)),
                        Uint8Array.from(addrEnc.encode(depositData.recipient)),
                        Uint8Array.from(addrEnc.encode(depositData.inputToken)),
                        Uint8Array.from(addrEnc.encode(depositData.outputToken)),
                        Uint8Array.from(u64.encode(depositData.inputAmount)),
                        Uint8Array.from(depositData.outputAmount),
                        Uint8Array.from(u64.encode(depositData.destinationChainId)),
                        Uint8Array.from(addrEnc.encode(depositData.exclusiveRelayer)),
                        Uint8Array.from(u32.encode(depositData.quoteTimestamp)),
                        Uint8Array.from(u32.encode(depositData.fillDeadline)),
                        Uint8Array.from(u32.encode(depositData.exclusivityParameter)),
                        Uint8Array.from(u32.encode(BigInt(depositData.message.length))),
                        depositData.message,
                    ];
                    seedHash = Buffer.from((0, utils_2.keccak256)(Buffer.concat(parts)).slice(2), "hex");
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: programId,
                            seeds: [Buffer.from("delegate"), seedHash],
                        })];
                case 1:
                    pda = (_a.sent())[0];
                    return [2, pda];
            }
        });
    });
}
exports.getDepositDelegatePda = getDepositDelegatePda;
function getDepositNowDelegatePda(depositData, programId) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var addrEnc, u64, u32, parts, seedHash, pda;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    addrEnc = (0, kit_1.getAddressEncoder)();
                    u64 = (0, kit_1.getU64Encoder)();
                    u32 = (0, kit_1.getU32Encoder)();
                    parts = [
                        Uint8Array.from(addrEnc.encode(depositData.depositor)),
                        Uint8Array.from(addrEnc.encode(depositData.recipient)),
                        Uint8Array.from(addrEnc.encode(depositData.inputToken)),
                        Uint8Array.from(addrEnc.encode(depositData.outputToken)),
                        Uint8Array.from(u64.encode(depositData.inputAmount)),
                        Uint8Array.from(depositData.outputAmount),
                        Uint8Array.from(u64.encode(depositData.destinationChainId)),
                        Uint8Array.from(addrEnc.encode(depositData.exclusiveRelayer)),
                        Uint8Array.from(u32.encode(depositData.fillDeadlineOffset)),
                        Uint8Array.from(u32.encode(depositData.exclusivityPeriod)),
                        Uint8Array.from(u32.encode(BigInt(depositData.message.length))),
                        depositData.message,
                    ];
                    seedHash = Buffer.from((0, utils_2.keccak256)(Buffer.concat(parts)).slice(2), "hex");
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: programId,
                            seeds: [Buffer.from("delegate"), seedHash],
                        })];
                case 1:
                    pda = (_a.sent())[0];
                    return [2, pda];
            }
        });
    });
}
exports.getDepositNowDelegatePda = getDepositNowDelegatePda;
function getFillRelayDelegatePda(relayHash, repaymentChainId, repaymentAddress, programId) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var addrEnc, u64, parts, seedHash, pda;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    addrEnc = (0, kit_1.getAddressEncoder)();
                    u64 = (0, kit_1.getU64Encoder)();
                    parts = [
                        relayHash,
                        Uint8Array.from(u64.encode(repaymentChainId)),
                        Uint8Array.from(addrEnc.encode(repaymentAddress)),
                    ];
                    seedHash = Buffer.from((0, utils_2.keccak256)(Buffer.concat(parts)).slice(2), "hex");
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: programId,
                            seeds: [Buffer.from("delegate"), seedHash],
                        })];
                case 1:
                    pda = (_a.sent())[0];
                    return [2, pda];
            }
        });
    });
}
exports.getFillRelayDelegatePda = getFillRelayDelegatePda;
var hasCCTPV1MessageBeenProcessed = function (solanaClient, signer, nonce, sourceDomain) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
    var noncePda, isNonceUsedIx, parserFunction;
    return tslib_1.__generator(this, function (_a) {
        switch (_a.label) {
            case 0: return [4, (0, _1.getCCTPNoncePda)(solanaClient, signer, nonce, sourceDomain)];
            case 1:
                noncePda = _a.sent();
                return [4, contracts_1.MessageTransmitterClient.getIsNonceUsedInstruction({
                        nonce: nonce,
                        usedNonces: noncePda,
                    })];
            case 2:
                isNonceUsedIx = _a.sent();
                parserFunction = function (buf) {
                    if (buf.length != 1) {
                        throw new Error("Invalid buffer length for isNonceUsedIx");
                    }
                    return Boolean(buf[0]);
                };
                return [4, (0, _1.simulateAndDecode)(solanaClient, isNonceUsedIx, signer, parserFunction)];
            case 3: return [2, _a.sent()];
        }
    });
}); };
exports.hasCCTPV1MessageBeenProcessed = hasCCTPV1MessageBeenProcessed;
function getAccountMetasForTokenlessMessage() {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var statePda, _a;
        var _b, _c;
        return tslib_1.__generator(this, function (_d) {
            switch (_d.label) {
                case 0: return [4, (0, _1.getStatePda)(contracts_1.SvmSpokeClient.SVM_SPOKE_PROGRAM_ADDRESS)];
                case 1:
                    statePda = _d.sent();
                    _a = [{ address: statePda, role: kit_1.AccountRole.READONLY }];
                    _b = {};
                    return [4, (0, _1.getSelfAuthority)()];
                case 2:
                    _a = _a.concat([
                        (_b.address = _d.sent(), _b.role = kit_1.AccountRole.READONLY, _b),
                        { address: contracts_1.SvmSpokeClient.SVM_SPOKE_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
                        { address: statePda, role: kit_1.AccountRole.WRITABLE }
                    ]);
                    _c = {};
                    return [4, (0, _1.getEventAuthority)(contracts_1.SvmSpokeClient.SVM_SPOKE_PROGRAM_ADDRESS)];
                case 3: return [2, _a.concat([
                        (_c.address = _d.sent(), _c.role = kit_1.AccountRole.READONLY, _c),
                        { address: contracts_1.SvmSpokeClient.SVM_SPOKE_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY }
                    ])];
            }
        });
    });
}
exports.getAccountMetasForTokenlessMessage = getAccountMetasForTokenlessMessage;
function getAccountMetasForDepositMessage(message, hubChainId, tokenMessengerMinter) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var l1Usdc, l2Usdc, tokenMessengerPda, tokenMinterPda, localTokenPda, tokenMessengerEventAuthorityPda, custodyTokenAccountPda, state, tokenProgram, vault, tokenPairPda, remoteTokenMessengerPda;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    l1Usdc = utils_2.EvmAddress.from(constants_1.TOKEN_SYMBOLS_MAP.USDC.addresses[hubChainId]);
                    l2Usdc = utils_2.SvmAddress.from(constants_1.TOKEN_SYMBOLS_MAP.USDC.addresses[(0, utils_2.chainIsProd)(hubChainId) ? constants_1.CHAIN_IDs.SOLANA : constants_1.CHAIN_IDs.SOLANA_DEVNET]);
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: tokenMessengerMinter,
                            seeds: ["token_messenger"],
                        })];
                case 1:
                    tokenMessengerPda = (_a.sent())[0];
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: tokenMessengerMinter,
                            seeds: ["token_minter"],
                        })];
                case 2:
                    tokenMinterPda = (_a.sent())[0];
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: tokenMessengerMinter,
                            seeds: ["local_token", utils_2.bs58.decode(l2Usdc.toBase58())],
                        })];
                case 3:
                    localTokenPda = (_a.sent())[0];
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: tokenMessengerMinter,
                            seeds: ["__event_authority"],
                        })];
                case 4:
                    tokenMessengerEventAuthorityPda = (_a.sent())[0];
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: tokenMessengerMinter,
                            seeds: ["custody", utils_2.bs58.decode(l2Usdc.toBase58())],
                        })];
                case 5:
                    custodyTokenAccountPda = (_a.sent())[0];
                    return [4, (0, _1.getStatePda)(contracts_1.SvmSpokeClient.SVM_SPOKE_PROGRAM_ADDRESS)];
                case 6:
                    state = _a.sent();
                    tokenProgram = token_1.TOKEN_PROGRAM_ADDRESS;
                    return [4, getAssociatedTokenAddress(utils_2.SvmAddress.from(state), utils_2.SvmAddress.from(l2Usdc.toBase58()), tokenProgram)];
                case 7:
                    vault = _a.sent();
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: tokenMessengerMinter,
                            seeds: [
                                new Uint8Array(Buffer.from("token_pair")),
                                new Uint8Array(Buffer.from(String(message.sourceDomain))),
                                new Uint8Array(Buffer.from(l1Usdc.toBytes32().slice(2), "hex")),
                            ],
                        })];
                case 8:
                    tokenPairPda = (_a.sent())[0];
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: tokenMessengerMinter,
                            seeds: ["remote_token_messenger", String(message.sourceDomain)],
                        })];
                case 9:
                    remoteTokenMessengerPda = (_a.sent())[0];
                    return [2, [
                            { address: tokenMessengerPda, role: kit_1.AccountRole.READONLY },
                            { address: remoteTokenMessengerPda, role: kit_1.AccountRole.READONLY },
                            { address: tokenMinterPda, role: kit_1.AccountRole.WRITABLE },
                            { address: localTokenPda, role: kit_1.AccountRole.WRITABLE },
                            { address: tokenPairPda, role: kit_1.AccountRole.READONLY },
                            { address: vault, role: kit_1.AccountRole.WRITABLE },
                            { address: custodyTokenAccountPda, role: kit_1.AccountRole.WRITABLE },
                            { address: token_1.TOKEN_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
                            { address: tokenMessengerEventAuthorityPda, role: kit_1.AccountRole.READONLY },
                            { address: tokenMessengerMinter, role: kit_1.AccountRole.READONLY },
                        ]];
            }
        });
    });
}
function getCCTPV1ReceiveMessageTx(solanaClient, signer, message, hubChainId) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var messageTransmitterPda, eventAuthorityPda, cctpMessageReceiver, authorityPda, usedNonces, accountMetas, _a, messageBytes, input;
        return tslib_1.__generator(this, function (_b) {
            switch (_b.label) {
                case 0: return [4, (0, kit_1.getProgramDerivedAddress)({
                        programAddress: contracts_1.MessageTransmitterClient.MESSAGE_TRANSMITTER_PROGRAM_ADDRESS,
                        seeds: ["message_transmitter"],
                    })];
                case 1:
                    messageTransmitterPda = (_b.sent())[0];
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: contracts_1.MessageTransmitterClient.MESSAGE_TRANSMITTER_PROGRAM_ADDRESS,
                            seeds: ["__event_authority"],
                        })];
                case 2:
                    eventAuthorityPda = (_b.sent())[0];
                    cctpMessageReceiver = (0, _1.isDepositForBurnEvent)(message)
                        ? contracts_1.TokenMessengerMinterClient.TOKEN_MESSENGER_MINTER_PROGRAM_ADDRESS
                        : contracts_1.SvmSpokeClient.SVM_SPOKE_PROGRAM_ADDRESS;
                    return [4, (0, kit_1.getProgramDerivedAddress)({
                            programAddress: contracts_1.MessageTransmitterClient.MESSAGE_TRANSMITTER_PROGRAM_ADDRESS,
                            seeds: ["message_transmitter_authority", utils_2.bs58.decode(cctpMessageReceiver)],
                        })];
                case 3:
                    authorityPda = (_b.sent())[0];
                    return [4, (0, _1.getCCTPNoncePda)(solanaClient, signer, message.nonce, message.sourceDomain)];
                case 4:
                    usedNonces = _b.sent();
                    if (!(0, _1.isDepositForBurnEvent)(message)) return [3, 6];
                    return [4, getAccountMetasForDepositMessage(message, hubChainId, contracts_1.TokenMessengerMinterClient.TOKEN_MESSENGER_MINTER_PROGRAM_ADDRESS)];
                case 5:
                    _a = _b.sent();
                    return [3, 8];
                case 6: return [4, getAccountMetasForTokenlessMessage()];
                case 7:
                    _a = _b.sent();
                    _b.label = 8;
                case 8:
                    accountMetas = _a;
                    messageBytes = message.messageBytes.startsWith("0x")
                        ? Buffer.from(message.messageBytes.slice(2), "hex")
                        : Buffer.from(message.messageBytes, "hex");
                    input = {
                        program: contracts_1.MessageTransmitterClient.MESSAGE_TRANSMITTER_PROGRAM_ADDRESS,
                        payer: signer,
                        caller: signer,
                        authorityPda: authorityPda,
                        messageTransmitter: messageTransmitterPda,
                        eventAuthority: eventAuthorityPda,
                        usedNonces: usedNonces,
                        receiver: contracts_1.SvmSpokeClient.SVM_SPOKE_PROGRAM_ADDRESS,
                        systemProgram: system_1.SYSTEM_PROGRAM_ADDRESS,
                        message: messageBytes,
                        attestation: Buffer.from(message.attestation.slice(2), "hex"),
                    };
                    return [2, (0, exports.createReceiveMessageInstruction)(signer, solanaClient, input, accountMetas)];
            }
        });
    });
}
exports.getCCTPV1ReceiveMessageTx = getCCTPV1ReceiveMessageTx;
function finalizeCCTPV1Messages(solanaClient, attestedMessages, signer, simulate, hubChainId) {
    var _this = this;
    if (simulate === void 0) { simulate = false; }
    if (hubChainId === void 0) { hubChainId = 1; }
    return (0, utils_2.mapAsync)(attestedMessages, function (message) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
        var receiveMessageIx, result, _a, _b, _c, signedTransaction, signature, encodedTransaction;
        return tslib_1.__generator(this, function (_d) {
            switch (_d.label) {
                case 0: return [4, getCCTPV1ReceiveMessageTx(solanaClient, signer, message, hubChainId)];
                case 1:
                    receiveMessageIx = _d.sent();
                    if (!simulate) return [3, 4];
                    _b = (_a = solanaClient)
                        .simulateTransaction;
                    _c = kit_1.getBase64EncodedWireTransaction;
                    return [4, (0, kit_1.signTransactionMessageWithSigners)(receiveMessageIx)];
                case 2: return [4, _b.apply(_a, [_c.apply(void 0, [_d.sent()]),
                        {
                            encoding: "base64",
                        }])
                        .send()];
                case 3:
                    result = _d.sent();
                    if (result.value.err) {
                        throw new Error(result.value.err.toString());
                    }
                    return [2, ""];
                case 4: return [4, (0, kit_1.signTransactionMessageWithSigners)(receiveMessageIx)];
                case 5:
                    signedTransaction = _d.sent();
                    signature = (0, kit_1.getSignatureFromTransaction)(signedTransaction);
                    encodedTransaction = (0, kit_1.getBase64EncodedWireTransaction)(signedTransaction);
                    return [4, solanaClient
                            .sendTransaction(encodedTransaction, { preflightCommitment: "confirmed", encoding: "base64" })
                            .send()];
                case 6:
                    _d.sent();
                    return [2, signature];
            }
        });
    }); });
}
exports.finalizeCCTPV1Messages = finalizeCCTPV1Messages;
//# sourceMappingURL=SpokeUtils.js.map