"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AttestationResponse = exports.AttestationMessage = exports.DecodedMessage = exports.DecodedMessageBody = exports.decodeTokenMessengerV2MessageBody = exports.decodeMessageHeaderV2 = exports.decodeMessageSentDataV2 = exports.EVENT_ACCOUNT_WINDOW_SECONDS = void 0;
exports.getV2BurnAttestation = getV2BurnAttestation;
var tslib_1 = require("tslib");
var anchor = tslib_1.__importStar(require("@coral-xyz/anchor"));
var superstruct_1 = require("superstruct");
var ethers_1 = require("ethers");
var relayHashUtils_1 = require("./relayHashUtils");
var conversionUtils_1 = require("./conversionUtils");
var HEADER_VERSION_INDEX = 0;
var SOURCE_DOMAIN_INDEX = 4;
var DESTINATION_DOMAIN_INDEX = 8;
var NONCE_INDEX = 12;
var HEADER_SENDER_INDEX = 44;
var HEADER_RECIPIENT_INDEX = 76;
var DESTINATION_CALLER_INDEX = 108;
var MIN_FINALITY_THRESHOLD_INDEX = 140;
var FINALITY_THRESHOLD_EXECUTED_INDEX = 144;
var MESSAGE_BODY_INDEX = 148;
var BODY_VERSION_INDEX = 0;
var BURN_TOKEN_INDEX = 4;
var MINT_RECIPIENT_INDEX = 36;
var AMOUNT_INDEX = 68;
var MESSAGE_SENDER_INDEX = 100;
var MAX_FEE_INDEX = 132;
var FEE_EXECUTED_INDEX = 164;
var EXPIRATION_BLOCK = 196;
var HOOK_DATA_INDEX = 228;
exports.EVENT_ACCOUNT_WINDOW_SECONDS = 60 * 60 * 24 * 5;
var decodeMessageSentDataV2 = function (message) {
    var messageHeader = (0, exports.decodeMessageHeaderV2)(message);
    var messageBodyData = message.slice(MESSAGE_BODY_INDEX);
    var messageBody = (0, exports.decodeTokenMessengerV2MessageBody)(messageBodyData);
    return tslib_1.__assign(tslib_1.__assign({}, messageHeader), { messageBody: messageBody });
};
exports.decodeMessageSentDataV2 = decodeMessageSentDataV2;
var decodeMessageHeaderV2 = function (data) {
    var version = data.readUInt32BE(HEADER_VERSION_INDEX);
    var sourceDomain = data.readUInt32BE(SOURCE_DOMAIN_INDEX);
    var destinationDomain = data.readUInt32BE(DESTINATION_DOMAIN_INDEX);
    var nonce = (0, relayHashUtils_1.readUInt256BE)(data.slice(NONCE_INDEX, NONCE_INDEX + 32));
    var sender = new anchor.web3.PublicKey(data.slice(HEADER_SENDER_INDEX, HEADER_SENDER_INDEX + 32));
    var recipient = new anchor.web3.PublicKey(data.slice(HEADER_RECIPIENT_INDEX, HEADER_RECIPIENT_INDEX + 32));
    var destinationCaller = new anchor.web3.PublicKey(data.slice(DESTINATION_CALLER_INDEX, DESTINATION_CALLER_INDEX + 32));
    var minFinalityThreshold = data.readUInt32BE(MIN_FINALITY_THRESHOLD_INDEX);
    var finalityThresholdExecuted = data.readUInt32BE(FINALITY_THRESHOLD_EXECUTED_INDEX);
    var messageBody = data.slice(MESSAGE_BODY_INDEX);
    return {
        version: version,
        sourceDomain: sourceDomain,
        destinationDomain: destinationDomain,
        nonce: nonce,
        sender: sender,
        recipient: recipient,
        destinationCaller: destinationCaller,
        minFinalityThreshold: minFinalityThreshold,
        finalityThresholdExecuted: finalityThresholdExecuted,
        messageBody: messageBody,
    };
};
exports.decodeMessageHeaderV2 = decodeMessageHeaderV2;
var decodeTokenMessengerV2MessageBody = function (data) {
    var version = data.readUInt32BE(BODY_VERSION_INDEX);
    var burnToken = new anchor.web3.PublicKey(data.slice(BURN_TOKEN_INDEX, BURN_TOKEN_INDEX + 32));
    var mintRecipient = new anchor.web3.PublicKey(data.slice(MINT_RECIPIENT_INDEX, MINT_RECIPIENT_INDEX + 32));
    var amount = (0, relayHashUtils_1.readUInt256BE)(data.slice(AMOUNT_INDEX, AMOUNT_INDEX + 32));
    var messageSender = new anchor.web3.PublicKey(data.slice(MESSAGE_SENDER_INDEX, MESSAGE_SENDER_INDEX + 32));
    var maxFee = (0, relayHashUtils_1.readUInt256BE)(data.slice(MAX_FEE_INDEX, MAX_FEE_INDEX + 32));
    var feeExecuted = (0, relayHashUtils_1.readUInt256BE)(data.slice(FEE_EXECUTED_INDEX, FEE_EXECUTED_INDEX + 32));
    var expirationBlock = (0, relayHashUtils_1.readUInt256BE)(data.slice(EXPIRATION_BLOCK, EXPIRATION_BLOCK + 32));
    var hookData = data.slice(HOOK_DATA_INDEX);
    return { version: version, burnToken: burnToken, mintRecipient: mintRecipient, amount: amount, messageSender: messageSender, maxFee: maxFee, feeExecuted: feeExecuted, expirationBlock: expirationBlock, hookData: hookData };
};
exports.decodeTokenMessengerV2MessageBody = decodeTokenMessengerV2MessageBody;
exports.DecodedMessageBody = (0, superstruct_1.object)({
    burnToken: (0, superstruct_1.string)(),
    mintRecipient: (0, superstruct_1.string)(),
    amount: (0, superstruct_1.string)(),
    messageSender: (0, superstruct_1.string)(),
    maxFee: (0, superstruct_1.optional)((0, superstruct_1.string)()),
    feeExecuted: (0, superstruct_1.optional)((0, superstruct_1.string)()),
    expirationBlock: (0, superstruct_1.optional)((0, superstruct_1.string)()),
    hookData: (0, superstruct_1.optional)((0, superstruct_1.string)()),
});
exports.DecodedMessage = (0, superstruct_1.object)({
    sourceDomain: (0, superstruct_1.string)(),
    destinationDomain: (0, superstruct_1.string)(),
    nonce: (0, superstruct_1.string)(),
    sender: (0, superstruct_1.string)(),
    recipient: (0, superstruct_1.string)(),
    destinationCaller: (0, superstruct_1.string)(),
    minFinalityThreshold: (0, superstruct_1.optional)((0, superstruct_1.enums)(["1000", "2000"])),
    finalityThresholdExecuted: (0, superstruct_1.optional)((0, superstruct_1.enums)(["1000", "2000"])),
    messageBody: (0, superstruct_1.string)(),
    decodedMessageBody: (0, superstruct_1.optional)((0, superstruct_1.coerce)((0, superstruct_1.nullable)(exports.DecodedMessageBody), (0, superstruct_1.union)([(0, superstruct_1.nullable)(exports.DecodedMessageBody), (0, superstruct_1.object)({})]), function (v) {
        return isEmptyObject(v) ? null : v;
    })),
});
exports.AttestationMessage = (0, superstruct_1.object)({
    message: (0, superstruct_1.string)(),
    eventNonce: (0, superstruct_1.string)(),
    attestation: (0, superstruct_1.string)(),
    decodedMessage: (0, superstruct_1.optional)((0, superstruct_1.coerce)((0, superstruct_1.nullable)(exports.DecodedMessage), (0, superstruct_1.union)([(0, superstruct_1.nullable)(exports.DecodedMessage), (0, superstruct_1.object)({})]), function (v) {
        return isEmptyObject(v) ? null : v;
    })),
    cctpVersion: (0, superstruct_1.enums)([1, 2]),
    status: (0, superstruct_1.enums)(["complete", "pending_confirmations"]),
    delayReason: (0, superstruct_1.optional)((0, superstruct_1.nullable)((0, superstruct_1.enums)(["insufficient_fee", "amount_above_max", "insufficient_allowance_available"]))),
});
exports.AttestationResponse = (0, superstruct_1.object)({
    messages: (0, superstruct_1.array)(exports.AttestationMessage),
});
var isEmptyObject = function (v) {
    return v != null && typeof v === "object" && !Array.isArray(v) && Object.keys(v).length === 0;
};
function getV2BurnAttestation(txSignature, sourceMessageData, irisApiUrl) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var sourceMessage, attestationResponse, _i, _a, message;
        return tslib_1.__generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    sourceMessage = (0, exports.decodeMessageSentDataV2)(sourceMessageData);
                    return [4, fetch("".concat(irisApiUrl, "/v2/messages/").concat(sourceMessage.sourceDomain, "/?transactionHash=").concat(txSignature))];
                case 1: return [4, (_b.sent()).json()];
                case 2:
                    attestationResponse = _b.sent();
                    if (attestationResponse.error)
                        return [2, null];
                    (0, superstruct_1.assert)(attestationResponse, exports.AttestationResponse);
                    for (_i = 0, _a = attestationResponse.messages; _i < _a.length; _i++) {
                        message = _a[_i];
                        if (message.message !== "0x" &&
                            message.attestation !== "PENDING" &&
                            !!message.decodedMessage &&
                            isMatchingV2BurnMessage(sourceMessage, message.decodedMessage)) {
                            return [2, {
                                    destinationMessage: Buffer.from(ethers_1.ethers.utils.arrayify(message.message)),
                                    attestation: Buffer.from(ethers_1.ethers.utils.arrayify(message.attestation)),
                                }];
                        }
                    }
                    return [2, null];
            }
        });
    });
}
function isMatchingV2BurnMessage(sourceMessage, destinationMessage) {
    if (!destinationMessage.decodedMessageBody)
        return false;
    return (sourceMessage.sourceDomain.toString() === destinationMessage.sourceDomain &&
        sourceMessage.destinationDomain.toString() === destinationMessage.destinationDomain &&
        (0, conversionUtils_1.addressOrBase58ToBytes32)(sourceMessage.sender.toString()) === (0, conversionUtils_1.addressOrBase58ToBytes32)(destinationMessage.sender) &&
        (0, conversionUtils_1.addressOrBase58ToBytes32)(sourceMessage.recipient.toString()) ===
            (0, conversionUtils_1.addressOrBase58ToBytes32)(destinationMessage.recipient) &&
        (0, conversionUtils_1.addressOrBase58ToBytes32)(sourceMessage.destinationCaller.toString()) ===
            (0, conversionUtils_1.addressOrBase58ToBytes32)(destinationMessage.destinationCaller) &&
        sourceMessage.minFinalityThreshold.toString() === destinationMessage.minFinalityThreshold &&
        (0, conversionUtils_1.addressOrBase58ToBytes32)(sourceMessage.messageBody.burnToken.toString()) ===
            (0, conversionUtils_1.addressOrBase58ToBytes32)(destinationMessage.decodedMessageBody.burnToken) &&
        (0, conversionUtils_1.addressOrBase58ToBytes32)(sourceMessage.messageBody.mintRecipient.toString()) ===
            (0, conversionUtils_1.addressOrBase58ToBytes32)(destinationMessage.decodedMessageBody.mintRecipient) &&
        sourceMessage.messageBody.amount.toString() === destinationMessage.decodedMessageBody.amount &&
        (0, conversionUtils_1.addressOrBase58ToBytes32)(sourceMessage.messageBody.messageSender.toString()) ===
            (0, conversionUtils_1.addressOrBase58ToBytes32)(destinationMessage.decodedMessageBody.messageSender) &&
        sourceMessage.messageBody.maxFee.toString() === destinationMessage.decodedMessageBody.maxFee &&
        sourceMessage.messageBody.hookData.equals(Buffer.from(ethers_1.ethers.utils.arrayify(destinationMessage.decodedMessageBody.hookData || "0x"))));
}
//# sourceMappingURL=cctpV2Helpers.js.map