import { __assign, __awaiter, __generator } from "tslib";
import * as anchor from "@coral-xyz/anchor";
import { array, object, optional, string } from "superstruct";
import { readUInt256BE } from "./relayHashUtils";
// Index positions to decode Message Header from
// https://developers.circle.com/cctp/v1/message-format#cctp-v1-message-header
var HEADER_VERSION_INDEX = 0;
var SOURCE_DOMAIN_INDEX = 4;
var DESTINATION_DOMAIN_INDEX = 8;
var NONCE_INDEX = 12;
var HEADER_SENDER_INDEX = 20;
var HEADER_RECIPIENT_INDEX = 52;
var DESTINATION_CALLER_INDEX = 84;
var MESSAGE_BODY_INDEX = 116;
// Index positions to decode Message Body for TokenMessenger from
// https://developers.circle.com/cctp/v1/message-format#cctp-v1-message-body
var BODY_VERSION_INDEX = 0;
var BURN_TOKEN_INDEX = 4;
var MINT_RECIPIENT_INDEX = 36;
var AMOUNT_INDEX = 68;
var MESSAGE_SENDER_INDEX = 100;
/**
 * Decodes a CCTP message into a MessageHeader and TokenMessengerMessageBody.
 */
export var decodeMessageSentData = function (message) {
    var messageHeader = decodeMessageHeader(message);
    var messageBodyData = message.slice(MESSAGE_BODY_INDEX);
    var messageBody = decodeTokenMessengerMessageBody(messageBodyData);
    return __assign(__assign({}, messageHeader), { messageBody: messageBody });
};
/**
 * Decodes a CCTP message header.
 */
export var decodeMessageHeader = 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 = data.readBigUInt64BE(NONCE_INDEX);
    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 messageBody = data.slice(MESSAGE_BODY_INDEX);
    return {
        version: version,
        sourceDomain: sourceDomain,
        destinationDomain: destinationDomain,
        nonce: nonce,
        sender: sender,
        recipient: recipient,
        destinationCaller: destinationCaller,
        messageBody: messageBody,
    };
};
/**
 * Decodes a TokenMessenger message body.
 */
export var decodeTokenMessengerMessageBody = 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 = readUInt256BE(data.slice(AMOUNT_INDEX, AMOUNT_INDEX + 32));
    var messageSender = new anchor.web3.PublicKey(data.slice(MESSAGE_SENDER_INDEX, MESSAGE_SENDER_INDEX + 32));
    return { version: version, burnToken: burnToken, mintRecipient: mintRecipient, amount: amount, messageSender: messageSender };
};
/**
 * Encodes a MessageHeader into a Buffer.
 */
export var encodeMessageHeader = function (header) {
    var message = Buffer.alloc(MESSAGE_BODY_INDEX + header.messageBody.length);
    message.writeUInt32BE(header.version, HEADER_VERSION_INDEX);
    message.writeUInt32BE(header.sourceDomain, SOURCE_DOMAIN_INDEX);
    message.writeUInt32BE(header.destinationDomain, DESTINATION_DOMAIN_INDEX);
    message.writeBigUInt64BE(header.nonce, NONCE_INDEX);
    header.sender.toBuffer().copy(message, HEADER_SENDER_INDEX);
    header.recipient.toBuffer().copy(message, HEADER_RECIPIENT_INDEX);
    header.destinationCaller.toBuffer().copy(message, DESTINATION_CALLER_INDEX);
    header.messageBody.copy(message, MESSAGE_BODY_INDEX);
    return message;
};
/**
 * Structure for the attestation response from the attestation service.
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var AttestationResponseStruct = object({
    error: optional(string()),
    messages: array(object({
        attestation: string(),
        message: string(),
        eventNonce: string(),
    })),
});
/**
 * Fetches attestation from attestation service given the txHash.
 */
export var getMessages = function (txHash, srcDomain, irisApiUrl) { return __awaiter(void 0, void 0, void 0, function () {
    var attestationResponse, response;
    var _a, _b, _c, _d;
    return __generator(this, function (_e) {
        switch (_e.label) {
            case 0:
                console.log("Fetching attestations and messages for tx...", txHash);
                attestationResponse = {};
                _e.label = 1;
            case 1:
                if (!(attestationResponse.error ||
                    !attestationResponse.messages ||
                    ((_b = (_a = attestationResponse.messages) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.attestation) === "PENDING")) return [3 /*break*/, 6];
                return [4 /*yield*/, fetch("".concat(irisApiUrl, "/messages/").concat(srcDomain, "/").concat(txHash))];
            case 2:
                response = _e.sent();
                return [4 /*yield*/, response.json()];
            case 3:
                attestationResponse = _e.sent();
                if (!(attestationResponse.error ||
                    !attestationResponse.messages ||
                    ((_d = (_c = attestationResponse.messages) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.attestation) === "PENDING")) return [3 /*break*/, 5];
                return [4 /*yield*/, new Promise(function (r) { return setTimeout(r, 2000); })];
            case 4:
                _e.sent();
                _e.label = 5;
            case 5: return [3 /*break*/, 1];
            case 6:
                // Validate the response structure
                try {
                    AttestationResponseStruct.assert(attestationResponse);
                }
                catch (error) {
                    console.error("Invalid attestation response structure:", error);
                    throw new Error("Invalid attestation response structure");
                }
                return [2 /*return*/, attestationResponse];
        }
    });
}); };
//# sourceMappingURL=cctpHelpers.js.map