var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { BigNumber } from "ethers";
import { ethers_contracts } from "../..";
import { CHAINS, tryNativeToHexString, } from "../../utils";
import { getWormholeRelayerAddress } from "../consts";
export function sendToEvm(signer, sourceChain, targetChain, targetAddress, payload, gasLimit, overrides, sendOptionalParams) {
    return __awaiter(this, void 0, void 0, function* () {
        const sourceChainId = CHAINS[sourceChain];
        const targetChainId = CHAINS[targetChain];
        const environment = (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.environment) || "MAINNET";
        const wormholeRelayerAddress = (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.wormholeRelayerAddress) ||
            getWormholeRelayerAddress(sourceChain, environment);
        const sourceWormholeRelayer = ethers_contracts.IWormholeRelayer__factory.connect(wormholeRelayerAddress, signer);
        const refundLocationExists = (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.refundChainId) !== undefined &&
            (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.refundAddress) !== undefined;
        const defaultDeliveryProviderAddress = yield sourceWormholeRelayer.getDefaultDeliveryProvider();
        // Using the most general 'send' function in IWormholeRelayer
        // Inputs:
        // targetChainId, targetAddress, refundChainId, refundAddress, maxTransactionFee, receiverValue, payload, vaaKeys,
        // consistencyLevel, deliveryProviderAddress, relayParameters
        const [deliveryPrice] = yield sourceWormholeRelayer["quoteEVMDeliveryPrice(uint16,uint256,uint256,address)"](targetChainId, (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.receiverValue) || 0, gasLimit, (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.deliveryProviderAddress) ||
            defaultDeliveryProviderAddress);
        const value = yield ((overrides === null || overrides === void 0 ? void 0 : overrides.value) || 0);
        const totalPrice = deliveryPrice.add((sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.paymentForExtraReceiverValue) || 0);
        if (!totalPrice.eq(value)) {
            throw new Error(`Expected a payment of ${totalPrice.toString()} wei; received ${value.toString()} wei`);
        }
        const tx = sourceWormholeRelayer.sendToEvm(targetChainId, // targetChainId
        targetAddress, // targetAddress
        payload, (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.receiverValue) || 0, // receiverValue
        (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.paymentForExtraReceiverValue) || 0, // payment for extra receiverValue
        gasLimit, (refundLocationExists && (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.refundChainId)) ||
            sourceChainId, // refundChainId
        (refundLocationExists &&
            (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.refundAddress) &&
            (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.refundAddress)) ||
            signer.getAddress(), // refundAddress
        (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.deliveryProviderAddress) ||
            defaultDeliveryProviderAddress, // deliveryProviderAddress
        (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.additionalVaas)
            ? sendOptionalParams.additionalVaas.map((additionalVaa) => ({
                chainId: additionalVaa.chainId || sourceChainId,
                emitterAddress: Buffer.from(tryNativeToHexString(additionalVaa.emitterAddress, "ethereum"), "hex"),
                sequence: BigNumber.from(additionalVaa.sequenceNumber || 0),
            }))
            : [], // vaaKeys
        (sendOptionalParams === null || sendOptionalParams === void 0 ? void 0 : sendOptionalParams.consistencyLevel) || 15, // consistencyLevel
        overrides);
        return tx;
    });
}
