"use strict";
// This script finalizes the message on the SponsoredCCTPDstPeriphery contract.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("@across-protocol/constants");
const anchor = __importStar(require("@coral-xyz/anchor"));
const anchor_1 = require("@coral-xyz/anchor");
const yargs_1 = __importDefault(require("yargs"));
const helpers_1 = require("yargs/helpers");
const web3_v1_1 = require("../../../src/svm/web3-v1");
const ethers_1 = require("ethers");
const helpers_2 = require("../utils/helpers");
// Set up Solana provider and programs
const provider = anchor_1.AnchorProvider.env();
anchor.setProvider(provider);
const program = (0, web3_v1_1.getSponsoredCctpSrcPeripheryProgram)(provider);
const messageTransmitterV2Program = (0, web3_v1_1.getMessageTransmitterV2Program)(provider);
const irisApiUrl = (0, web3_v1_1.isSolanaDevnet)(provider) ? web3_v1_1.CIRCLE_IRIS_API_URL_DEVNET : web3_v1_1.CIRCLE_IRIS_API_URL_MAINNET;
// Set up Ethereum provider and signer.
const nodeURL = (0, helpers_2.requireEnv)("NODE_URL");
const ethersProvider = new ethers_1.ethers.providers.JsonRpcProvider(nodeURL);
const ethersSigner = ethers_1.ethers.Wallet.fromMnemonic((0, helpers_2.requireEnv)("MNEMONIC")).connect(ethersProvider);
const sponsoredCCTPDstPeripheryIface = new ethers_1.ethers.utils.Interface([
    "function receiveMessage(bytes message, bytes attestation, bytes signature)",
]);
// Parse arguments
const argvPromise = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv)).option("txSignature", {
    type: "string",
    demandOption: true,
    describe: "Transaction signature of the deposit to finalize",
}).argv;
async function getDeposits(txSignature) {
    const txResult = await provider.connection.getTransaction(txSignature, {
        commitment: "confirmed",
        maxSupportedTransactionVersion: 0,
    });
    if (!txResult) {
        throw new Error(`Transaction ${txSignature} not found`);
    }
    if (!!txResult.meta?.err) {
        throw new Error(`Transaction ${txSignature} failed: ${txResult.meta.err}`);
    }
    const events = (0, web3_v1_1.processEventFromTx)(txResult, [program]);
    const deposits = [];
    for (const [index, event] of events.entries()) {
        if (event.name === "sponsoredDepositForBurn") {
            const quoteSignature = event.data.signature;
            const nextIndex = index + 1;
            if (events.length < nextIndex || events[nextIndex].name !== "createdEventAccount") {
                throw new Error("Unexpected event sequence: expected 'createdEventAccount' after 'sponsoredDepositForBurn'");
            }
            const messageSentEventData = events[nextIndex].data.messageSentEventData;
            const messageSentAccount = await provider.connection.getAccountInfo(messageSentEventData);
            if (!messageSentAccount) {
                console.log(`MessageSent account ${messageSentEventData.toString()} does not exist, skipping.`);
                continue;
            }
            const sourceMessageData = (await messageTransmitterV2Program.account.messageSent.fetch(messageSentEventData))
                .message;
            deposits.push({ quoteSignature, sourceMessageData });
        }
    }
    if (deposits.length === 0) {
        throw new Error("No sponsored deposit events found in the transaction");
    }
    return deposits;
}
async function receiveMessage() {
    const argv = await argvPromise;
    const txSignature = argv.txSignature;
    const evmChainId = (await ethersProvider.getNetwork()).chainId;
    const evmCctpDomain = constants_1.PUBLIC_NETWORKS[evmChainId].cctpDomain;
    const deposits = await getDeposits(txSignature);
    for (const deposit of deposits) {
        const attestationResponse = await (0, web3_v1_1.getV2BurnAttestation)(txSignature, deposit.sourceMessageData, irisApiUrl);
        if (!attestationResponse) {
            console.log(`No matching attestation found for deposit in tx ${txSignature}, skipping.`);
            continue;
        }
        const sourceMessage = (0, web3_v1_1.decodeMessageSentDataV2)(deposit.sourceMessageData);
        const sponsoredCCTPDstPeripheryAddress = (0, web3_v1_1.publicKeyToEvmAddress)(sourceMessage.destinationCaller);
        if (sourceMessage.destinationDomain !== evmCctpDomain) {
            console.log(`Skipping deposit with destination domain ${sourceMessage.destinationDomain} not matching EVM CCTP domain ${evmCctpDomain}`);
            continue;
        }
        const destinationCallerCode = await ethersProvider.getCode(sponsoredCCTPDstPeripheryAddress);
        if (destinationCallerCode === "0x") {
            console.log(`Skipping deposit as destination caller ${sponsoredCCTPDstPeripheryAddress} is not a contract`);
            continue;
        }
        const sponsoredCCTPDstPeriphery = new ethers_1.ethers.Contract(sponsoredCCTPDstPeripheryAddress, sponsoredCCTPDstPeripheryIface, ethersSigner);
        console.log("Trying to finalize sponsored deposit with the following parameters:");
        console.log(`- source tx signature: ${txSignature}`);
        console.log(`- destination contract: ${sponsoredCCTPDstPeripheryAddress}`);
        console.log(`- destination message: ${attestationResponse.destinationMessage.toString("hex")}`);
        console.log(`- attestation: ${attestationResponse.attestation.toString("hex")}`);
        console.log(`- quote signature: 0x${deposit.quoteSignature.toString("hex")}`);
        try {
            const tx = await sponsoredCCTPDstPeriphery.receiveMessage(attestationResponse.destinationMessage, attestationResponse.attestation, deposit.quoteSignature);
            console.log(`\nTransaction sent successfully, transaction hash: ${tx.hash}, waiting for confirmation...`);
            const receipt = await tx.wait();
            console.log(`- Transaction confirmed in block ${receipt.blockNumber}`);
        }
        catch (error) {
            console.error(`\nError finalizing sponsored deposit: ${error}`);
            continue;
        }
    }
}
receiveMessage();
