import { writeMultichainBroadcast, } from '../../util/broadcasts.js';
import { CREATEX_ADDRESS, createXABI } from '../../util/createx/constants.js';
import { fromFoundryArtifactPath } from '../../util/forge/foundryProject.js';
import { runOperation, runOperationsMany } from '../../stores/operationStore.js';
import { requestTransactionTask } from '../../stores/transactionTaskStore.js';
import { getTransaction, sendTransaction, waitForTransactionReceipt, } from '@wagmi/core';
import { encodeFunctionData } from 'viem';
import { wagmiConfig } from '../../commands/_app.js';
export const executeTransactionOperation = ({ chainId, deterministicAddress, initCode, baseSalt, account, }) => {
    return {
        key: ['executeTransaction', chainId, deterministicAddress],
        fn: async () => {
            if (account) {
                return await sendTransaction(wagmiConfig, {
                    to: CREATEX_ADDRESS,
                    data: encodeFunctionData({
                        abi: createXABI,
                        functionName: 'deployCreate2',
                        args: [baseSalt, initCode],
                    }),
                    account,
                    chainId,
                });
            }
            return await requestTransactionTask({
                chainId,
                to: CREATEX_ADDRESS,
                data: encodeFunctionData({
                    abi: createXABI,
                    functionName: 'deployCreate2',
                    args: [baseSalt, initCode],
                }),
            });
        },
    };
};
export const writeBroadcastArtifactOperation = ({ foundryArtifactPath, contractArguments, deterministicAddress, broadcasts, }) => {
    return {
        key: ['writeBroadcastArtifact', foundryArtifactPath, deterministicAddress],
        fn: async () => {
            const { foundryProject, contractFileName } = await fromFoundryArtifactPath(foundryArtifactPath);
            const multichainBroadcast = {
                name: contractFileName,
                address: deterministicAddress,
                timestamp: Math.floor(Date.now() / 1000),
                type: 'CREATE2',
                contractArguments,
                foundryProjectRoot: foundryProject.baseDir,
                transactions: broadcasts.reduce((acc, broadcast) => {
                    acc[broadcast.chainId] = broadcast;
                    return acc;
                }, {}),
            };
            await writeMultichainBroadcast(multichainBroadcast);
        },
    };
};
export const deployCreate2 = async ({ wagmiConfig, deterministicAddress, initCode, baseSalt, chains, foundryArtifactPath, contractArguments, account, }) => {
    const transactionHashes = await runOperationsMany(chains.map(chain => executeTransactionOperation({
        chainId: chain.id,
        deterministicAddress,
        initCode,
        baseSalt,
        account,
    })));
    const receipts = await Promise.all(chains.map(async (chain, i) => {
        const receipt = await waitForTransactionReceipt(wagmiConfig, {
            chainId: chain.id,
            hash: transactionHashes[i],
        });
        return receipt;
    }));
    const transactions = await Promise.all(chains.map(async (chain, i) => {
        const transaction = await getTransaction(wagmiConfig, {
            chainId: chain.id,
            hash: transactionHashes[i],
        });
        return transaction;
    }));
    const broadcasts = transactions.map((transaction, i) => ({
        chainId: chains[i].id,
        hash: transactionHashes[i],
        transaction,
        receipt: receipts[i],
    }));
    await runOperation(writeBroadcastArtifactOperation({
        foundryArtifactPath,
        contractArguments,
        deterministicAddress,
        broadcasts,
    }));
    return broadcasts;
};
