import { __awaiter, __generator } from "tslib";
import "@nomiclabs/hardhat-ethers";
import "@openzeppelin/hardhat-upgrades";
import "hardhat-deploy";
import hre from "hardhat";
import { ethers as ethersLib } from "ethers";
import { getContractFactory } from "../utils/getContractFactory";
import { amountToDeposit, depositRelayerFeePct, destinationChainId, maxUint256, realizedLpFeePct, repaymentChainId, TokenRolesEnum, zeroAddress, randomAddress, } from "../constants";
var _a = ethersLib.utils, defaultAbiCoder = _a.defaultAbiCoder, keccak256 = _a.keccak256;
export { zeroAddress };
// ---------------------------------------------------------------------------
// Relay hash helpers
// ---------------------------------------------------------------------------
export function getRelayHash(_depositor, _recipient, _depositId, _originChainId, _destinationChainId, _destinationToken, _amount, _realizedLpFeePct, _relayerFeePct, _message) {
    var relayData = {
        depositor: _depositor,
        recipient: _recipient,
        destinationToken: _destinationToken,
        amount: _amount || amountToDeposit,
        originChainId: _originChainId.toString(),
        destinationChainId: _destinationChainId.toString(),
        realizedLpFeePct: _realizedLpFeePct || realizedLpFeePct,
        relayerFeePct: _relayerFeePct || depositRelayerFeePct,
        depositId: _depositId.toString(),
        message: _message || "0x",
    };
    var relayHash = keccak256(defaultAbiCoder.encode([
        "tuple(address depositor, address recipient, address destinationToken, uint256 amount, uint256 originChainId, uint256 destinationChainId, int64 realizedLpFeePct, int64 relayerFeePct, uint32 depositId, bytes message)",
    ], [relayData]));
    return { relayHash: relayHash, relayData: relayData };
}
export function getV3RelayHash(relayData, destChainId) {
    return keccak256(defaultAbiCoder.encode([
        "tuple(bytes32 depositor, bytes32 recipient, bytes32 exclusiveRelayer, bytes32 inputToken, bytes32 outputToken, uint256 inputAmount, uint256 outputAmount, uint256 originChainId, uint256 depositId, uint32 fillDeadline, uint32 exclusivityDeadline, bytes message)",
        "uint256 destinationChainId",
    ], [relayData, destChainId]));
}
export function getLegacyV3RelayHash(relayData, destChainId) {
    return keccak256(defaultAbiCoder.encode([
        "tuple(address depositor, address recipient, address exclusiveRelayer, address inputToken, address outputToken, uint256 inputAmount, uint256 outputAmount, uint256 originChainId, uint32 depositId, uint32 fillDeadline, uint32 exclusivityDeadline, bytes message)",
        "uint256 destinationChainId",
    ], [relayData, destChainId]));
}
// ---------------------------------------------------------------------------
// Parameter builders
// ---------------------------------------------------------------------------
export function getDepositParams(args) {
    var _a, _b, _c, _d;
    return [
        (_a = args.recipient) !== null && _a !== void 0 ? _a : randomAddress(),
        args.originToken,
        args.amount.toString(),
        args.destinationChainId.toString(),
        args.relayerFeePct.toString(),
        args.quoteTimestamp.toString(),
        (_b = args.message) !== null && _b !== void 0 ? _b : "0x",
        (_d = (_c = args === null || args === void 0 ? void 0 : args.maxCount) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : maxUint256.toString(),
    ];
}
export function getFillRelayParams(_relayData, _maxTokensToSend, _repaymentChain, _maxCount) {
    return [
        _relayData.depositor,
        _relayData.recipient,
        _relayData.destinationToken,
        _relayData.amount.toString(),
        _maxTokensToSend.toString(),
        _repaymentChain ? _repaymentChain.toString() : repaymentChainId.toString(),
        _relayData.originChainId,
        _relayData.realizedLpFeePct.toString(),
        _relayData.relayerFeePct.toString(),
        _relayData.depositId,
        _relayData.message || "0x",
        _maxCount ? _maxCount.toString() : maxUint256.toString(),
    ];
}
export function getFillRelayUpdatedFeeParams(_relayData, _maxTokensToSend, _updatedFee, _signature, _repaymentChain, _updatedRecipient, _updatedMessage, _maxCount) {
    return [
        _relayData.depositor,
        _relayData.recipient,
        _updatedRecipient || _relayData.recipient,
        _relayData.destinationToken,
        _relayData.amount.toString(),
        _maxTokensToSend.toString(),
        _repaymentChain ? _repaymentChain.toString() : repaymentChainId.toString(),
        _relayData.originChainId,
        _relayData.realizedLpFeePct.toString(),
        _relayData.relayerFeePct.toString(),
        _updatedFee.toString(),
        _relayData.depositId,
        _relayData.message,
        _updatedMessage || _relayData.message,
        _signature,
        _maxCount ? _maxCount.toString() : maxUint256.toString(),
    ];
}
export function getExecuteSlowRelayParams(_depositor, _recipient, _destToken, _amount, _originChainId, _realizedLpFeePct, _relayerFeePct, _depositId, _relayerRefundId, _message, _payoutAdjustment, _proof) {
    return [
        _depositor,
        _recipient,
        _destToken,
        _amount.toString(),
        _originChainId.toString(),
        _realizedLpFeePct.toString(),
        _relayerFeePct.toString(),
        _depositId.toString(),
        _relayerRefundId.toString(),
        _message,
        _payoutAdjustment.toString(),
        _proof,
    ];
}
// ---------------------------------------------------------------------------
// EIP-712 signature helpers
// ---------------------------------------------------------------------------
export function modifyRelayHelper(modifiedRelayerFeePct, depositId, originChainId, depositor, updatedRecipient, updatedMessage) {
    return __awaiter(this, void 0, void 0, function () {
        var typedData, signature;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    typedData = {
                        types: {
                            UpdateDepositDetails: [
                                { name: "depositId", type: "uint32" },
                                { name: "originChainId", type: "uint256" },
                                { name: "updatedRelayerFeePct", type: "int64" },
                                { name: "updatedRecipient", type: "address" },
                                { name: "updatedMessage", type: "bytes" },
                            ],
                        },
                        domain: {
                            name: "ACROSS-V2",
                            version: "1.0.0",
                            chainId: Number(originChainId),
                        },
                        message: {
                            depositId: depositId,
                            originChainId: originChainId,
                            updatedRelayerFeePct: modifiedRelayerFeePct,
                            updatedRecipient: updatedRecipient,
                            updatedMessage: updatedMessage,
                        },
                    };
                    return [4 /*yield*/, depositor._signTypedData(typedData.domain, typedData.types, typedData.message)];
                case 1:
                    signature = _a.sent();
                    return [2 /*return*/, { signature: signature }];
            }
        });
    });
}
export function getUpdatedV3DepositSignature(depositor, depositId, originChainId, updatedOutputAmount, updatedRecipient, updatedMessage) {
    return __awaiter(this, void 0, void 0, function () {
        var typedData;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    typedData = {
                        types: {
                            UpdateDepositDetails: [
                                { name: "depositId", type: "uint256" },
                                { name: "originChainId", type: "uint256" },
                                { name: "updatedOutputAmount", type: "uint256" },
                                { name: "updatedRecipient", type: "bytes32" },
                                { name: "updatedMessage", type: "bytes" },
                            ],
                        },
                        domain: {
                            name: "ACROSS-V2",
                            version: "1.0.0",
                            chainId: originChainId,
                        },
                        message: {
                            depositId: depositId,
                            originChainId: originChainId,
                            updatedOutputAmount: updatedOutputAmount,
                            updatedRecipient: updatedRecipient,
                            updatedMessage: updatedMessage,
                        },
                    };
                    return [4 /*yield*/, depositor._signTypedData(typedData.domain, typedData.types, typedData.message)];
                case 1: return [2 /*return*/, _a.sent()];
            }
        });
    });
}
// ---------------------------------------------------------------------------
// Mock deployers
// ---------------------------------------------------------------------------
export function deployMockSpokePoolCaller(spokePool, rootBundleId, leaf, proof) {
    return __awaiter(this, void 0, void 0, function () {
        var _a, _b;
        return __generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    _a = getContractFactory;
                    _b = ["MockCaller"];
                    return [4 /*yield*/, hre.ethers.getSigners()];
                case 1: return [4 /*yield*/, _a.apply(void 0, _b.concat([(_c.sent())[0]]))];
                case 2: return [4 /*yield*/, (_c.sent()).deploy(spokePool.address, rootBundleId, leaf, proof)];
                case 3: return [2 /*return*/, _c.sent()];
            }
        });
    });
}
// ---------------------------------------------------------------------------
// Deployment
// ---------------------------------------------------------------------------
/**
 * Deploys a SpokePool with associated tokens for testing.
 * This is a local implementation that uses our local getContractFactory
 * instead of the one from @across-protocol/contracts.
 */
export function deploySpokePool(ethers_1) {
    return __awaiter(this, arguments, void 0, function (ethers, spokePoolName) {
        var _a, deployerWallet, crossChainAdmin, hubPool, weth, erc20, unwhitelistedErc20, destErc20, spokePool, _b, _c, erc1271;
        if (spokePoolName === void 0) { spokePoolName = "MockSpokePool"; }
        return __generator(this, function (_d) {
            switch (_d.label) {
                case 0: return [4 /*yield*/, ethers.getSigners()];
                case 1:
                    _a = _d.sent(), deployerWallet = _a[0], crossChainAdmin = _a[1], hubPool = _a[2];
                    return [4 /*yield*/, getContractFactory("WETH9", deployerWallet)];
                case 2: return [4 /*yield*/, (_d.sent()).deploy()];
                case 3:
                    weth = _d.sent();
                    return [4 /*yield*/, getContractFactory("ExpandedERC20", deployerWallet)];
                case 4: return [4 /*yield*/, (_d.sent()).deploy("USD Coin", "USDC", 18)];
                case 5:
                    erc20 = _d.sent();
                    return [4 /*yield*/, erc20.addMember(TokenRolesEnum.MINTER, deployerWallet.address)];
                case 6:
                    _d.sent();
                    return [4 /*yield*/, getContractFactory("ExpandedERC20", deployerWallet)];
                case 7: return [4 /*yield*/, (_d.sent()).deploy("Unwhitelisted", "UNWHITELISTED", 18)];
                case 8:
                    unwhitelistedErc20 = _d.sent();
                    return [4 /*yield*/, unwhitelistedErc20.addMember(TokenRolesEnum.MINTER, deployerWallet.address)];
                case 9:
                    _d.sent();
                    return [4 /*yield*/, getContractFactory("ExpandedERC20WithBlacklist", deployerWallet)];
                case 10: return [4 /*yield*/, (_d.sent()).deploy("L2 USD Coin", "L2 USDC", 18)];
                case 11:
                    destErc20 = _d.sent();
                    return [4 /*yield*/, destErc20.addMember(TokenRolesEnum.MINTER, deployerWallet.address)];
                case 12:
                    _d.sent();
                    _c = (_b = hre.upgrades).deployProxy;
                    return [4 /*yield*/, getContractFactory(spokePoolName, deployerWallet)];
                case 13: return [4 /*yield*/, _c.apply(_b, [_d.sent(), [0, crossChainAdmin.address, hubPool.address],
                        { kind: "uups", unsafeAllow: ["delegatecall"], constructorArgs: [weth.address] }])];
                case 14:
                    spokePool = _d.sent();
                    return [4 /*yield*/, spokePool.setChainId(destinationChainId)];
                case 15:
                    _d.sent();
                    return [4 /*yield*/, getContractFactory("MockERC1271", deployerWallet)];
                case 16: return [4 /*yield*/, (_d.sent()).deploy(deployerWallet.address)];
                case 17:
                    erc1271 = _d.sent();
                    return [2 /*return*/, {
                            weth: weth,
                            erc20: erc20,
                            spokePool: spokePool,
                            unwhitelistedErc20: unwhitelistedErc20,
                            destErc20: destErc20,
                            erc1271: erc1271,
                        }];
            }
        });
    });
}
/**
 * Creates a spoke pool fixture using hardhat-deploy's createFixture.
 */
export var spokePoolFixture = hre.deployments.createFixture(function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
    var ethers = _b.ethers;
    return __generator(this, function (_c) {
        switch (_c.label) {
            case 0: return [4 /*yield*/, deploySpokePool(ethers)];
            case 1: return [2 /*return*/, _c.sent()];
        }
    });
}); });
//# sourceMappingURL=SpokePool.Fixture.js.map