"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hubPoolFixture = void 0;
exports.setupHubPool = setupHubPool;
exports.deployHubPool = deployHubPool;
exports.enableTokensForLP = enableTokensForLP;
var tslib_1 = require("tslib");
require("@nomiclabs/hardhat-ethers");
require("@openzeppelin/hardhat-upgrades");
require("hardhat-deploy");
var hardhat_1 = tslib_1.__importDefault(require("hardhat"));
var getContractFactory_1 = require("../utils/getContractFactory");
var constants_1 = require("../constants");
var utils_1 = require("../utils");
var clients = tslib_1.__importStar(require("../../src/clients"));
var mocks_1 = require("../mocks");
var UmaEcosystemFixture_1 = require("./UmaEcosystemFixture");
function setupHubPool(ethers_1, maxRefundPerRelayerRefundLeaf_1, maxL1TokensPerPoolRebalanceLeaf_1) {
    return tslib_1.__awaiter(this, arguments, void 0, function (ethers, maxRefundPerRelayerRefundLeaf, maxL1TokensPerPoolRebalanceLeaf, destinationChainId, originChainId, lookbackForAllChains) {
        var _a, owner, depositor, relayer, dataworker, hubPoolChainId, _b, spokePool_1, erc20_1, _c, spokePool_2, erc20_2, spokePool_3, spokePool_4, spokePoolDeploymentBlocks, _d, _e, _f, _g, testChainIdList, umaEcosystem, _h, hubPool, hubPoolDeploymentBlock, l1Token_1, l1Token_2, _j, spyLogger, spy, configStore, configStoreClient, hubPoolClient, _k, spokePoolClient_1, spokePoolClient_2, spokePoolClient_3, spokePoolClient_4, spokePoolClients, _l, _m, _o, _p;
        var _q, _r;
        var _this = this;
        if (destinationChainId === void 0) { destinationChainId = constants_1.destinationChainId; }
        if (originChainId === void 0) { originChainId = constants_1.originChainId; }
        return tslib_1.__generator(this, function (_s) {
            switch (_s.label) {
                case 0: return [4, ethers.getSigners()];
                case 1:
                    _a = _s.sent(), owner = _a[0], depositor = _a[1], relayer = _a[2], dataworker = _a[3];
                    return [4, owner.getChainId()];
                case 2:
                    hubPoolChainId = _s.sent();
                    return [4, (0, utils_1.deploySpokePoolWithToken)(originChainId)];
                case 3:
                    _b = _s.sent(), spokePool_1 = _b.spokePool, erc20_1 = _b.erc20;
                    return [4, (0, utils_1.deploySpokePoolWithToken)(destinationChainId)];
                case 4:
                    _c = _s.sent(), spokePool_2 = _c.spokePool, erc20_2 = _c.erc20;
                    return [4, (0, utils_1.deploySpokePoolWithToken)(constants_1.repaymentChainId)];
                case 5:
                    spokePool_3 = (_s.sent()).spokePool;
                    return [4, (0, utils_1.deploySpokePoolWithToken)(hubPoolChainId)];
                case 6:
                    spokePool_4 = (_s.sent()).spokePool;
                    _q = {};
                    _d = originChainId;
                    return [4, spokePool_1.provider.getBlockNumber()];
                case 7:
                    _q[_d] = _s.sent();
                    _e = destinationChainId;
                    return [4, spokePool_2.provider.getBlockNumber()];
                case 8:
                    _q[_e] = _s.sent();
                    _f = constants_1.repaymentChainId;
                    return [4, spokePool_3.provider.getBlockNumber()];
                case 9:
                    _q[_f] = _s.sent();
                    _g = hubPoolChainId;
                    return [4, spokePool_4.provider.getBlockNumber()];
                case 10:
                    spokePoolDeploymentBlocks = (_q[_g] = _s.sent(),
                        _q);
                    testChainIdList = Object.keys(spokePoolDeploymentBlocks).map(function (_chainId) { return Number(_chainId); });
                    return [4, (0, UmaEcosystemFixture_1.setupUmaEcosystem)(owner)];
                case 11:
                    umaEcosystem = _s.sent();
                    return [4, (0, utils_1.deployAndConfigureHubPool)(owner, [
                            { l2ChainId: destinationChainId, spokePool: spokePool_2 },
                            { l2ChainId: originChainId, spokePool: spokePool_1 },
                            { l2ChainId: constants_1.repaymentChainId, spokePool: spokePool_3 },
                            { l2ChainId: hubPoolChainId, spokePool: spokePool_4 },
                        ], umaEcosystem.finder.address, umaEcosystem.timer.address)];
                case 12:
                    _h = _s.sent(), hubPool = _h.hubPool, hubPoolDeploymentBlock = _h.hubPoolDeploymentBlock, l1Token_1 = _h.l1Token_1, l1Token_2 = _h.l1Token_2;
                    return [4, (0, utils_1.enableRoutesOnHubPool)(hubPool, [
                            { destinationChainId: originChainId, l1Token: l1Token_1, destinationToken: erc20_1 },
                            { destinationChainId: destinationChainId, l1Token: l1Token_1, destinationToken: erc20_2 },
                            { destinationChainId: originChainId, l1Token: l1Token_2, destinationToken: erc20_2 },
                            { destinationChainId: destinationChainId, l1Token: l1Token_2, destinationToken: erc20_1 },
                            {
                                destinationChainId: hubPoolChainId,
                                l1Token: l1Token_1,
                                destinationToken: l1Token_1,
                            },
                            { destinationChainId: constants_1.repaymentChainId, l1Token: l1Token_1, destinationToken: l1Token_1 },
                        ])];
                case 13:
                    _s.sent();
                    return [4, umaEcosystem.collateralWhitelist.addToWhitelist(l1Token_1.address)];
                case 14:
                    _s.sent();
                    return [4, umaEcosystem.store.setFinalFee(l1Token_1.address, { rawValue: "0" })];
                case 15:
                    _s.sent();
                    return [4, hubPool.setBond(l1Token_1.address, "1")];
                case 16:
                    _s.sent();
                    return [4, (0, utils_1.setupTokensForWallet)(hubPool, dataworker, [l1Token_1], undefined, 100)];
                case 17:
                    _s.sent();
                    _j = (0, utils_1.createSpyLogger)(), spyLogger = _j.spyLogger, spy = _j.spy;
                    return [4, (0, utils_1.deployConfigStore)(owner, [l1Token_1, l1Token_2], maxL1TokensPerPoolRebalanceLeaf, maxRefundPerRelayerRefundLeaf)];
                case 18:
                    configStore = (_s.sent()).configStore;
                    configStoreClient = new mocks_1.MockConfigStoreClient(spyLogger, configStore);
                    configStoreClient.setAvailableChains(testChainIdList);
                    return [4, configStoreClient.update()];
                case 19:
                    _s.sent();
                    hubPoolClient = new clients.HubPoolClient(spyLogger, hubPool, configStoreClient, hubPoolDeploymentBlock, hubPoolChainId);
                    return [4, _constructSpokePoolClientsWithLookback([spokePool_1, spokePool_2, spokePool_3, spokePool_4], [originChainId, destinationChainId, constants_1.repaymentChainId, hubPoolChainId], spyLogger, relayer, hubPoolClient, lookbackForAllChains, spokePoolDeploymentBlocks)];
                case 20:
                    _k = _s.sent(), spokePoolClient_1 = _k[0], spokePoolClient_2 = _k[1], spokePoolClient_3 = _k[2], spokePoolClient_4 = _k[3];
                    spokePoolClients = (_r = {},
                        _r[originChainId] = spokePoolClient_1,
                        _r[destinationChainId] = spokePoolClient_2,
                        _r[constants_1.repaymentChainId] = spokePoolClient_3,
                        _r[hubPoolChainId] = spokePoolClient_4,
                        _r);
                    return [4, (0, utils_1.setupTokensForWallet)(spokePool_1, owner, [l1Token_1, l1Token_2], undefined, 100)];
                case 21:
                    _s.sent();
                    return [4, l1Token_1.approve(hubPool.address, constants_1.amountToLp)];
                case 22:
                    _s.sent();
                    return [4, l1Token_2.approve(hubPool.address, constants_1.amountToLp)];
                case 23:
                    _s.sent();
                    return [4, hubPool.addLiquidity(l1Token_1.address, constants_1.amountToLp)];
                case 24:
                    _s.sent();
                    return [4, hubPool.addLiquidity(l1Token_2.address, constants_1.amountToLp)];
                case 25:
                    _s.sent();
                    return [4, (0, utils_1.setupTokensForWallet)(spokePool_1, depositor, [erc20_1, erc20_2], undefined, 10)];
                case 26:
                    _s.sent();
                    return [4, (0, utils_1.setupTokensForWallet)(spokePool_2, depositor, [erc20_2, erc20_1], undefined, 10)];
                case 27:
                    _s.sent();
                    return [4, (0, utils_1.setupTokensForWallet)(spokePool_1, relayer, [erc20_1, erc20_2, l1Token_1, l1Token_2], undefined, 10)];
                case 28:
                    _s.sent();
                    return [4, (0, utils_1.setupTokensForWallet)(spokePool_2, relayer, [erc20_1, erc20_2, l1Token_1, l1Token_2], undefined, 10)];
                case 29:
                    _s.sent();
                    _m = (_l = spokePool_1).setCurrentTime;
                    return [4, (0, utils_1.getLastBlockTime)(spokePool_1.provider)];
                case 30: return [4, _m.apply(_l, [_s.sent()])];
                case 31:
                    _s.sent();
                    _p = (_o = spokePool_2).setCurrentTime;
                    return [4, (0, utils_1.getLastBlockTime)(spokePool_2.provider)];
                case 32: return [4, _p.apply(_o, [_s.sent()])];
                case 33:
                    _s.sent();
                    return [2, {
                            hubPool: hubPool,
                            spokePool_1: spokePool_1,
                            erc20_1: erc20_1,
                            spokePool_2: spokePool_2,
                            erc20_2: erc20_2,
                            l1Token_1: l1Token_1,
                            l1Token_2: l1Token_2,
                            configStore: configStore,
                            timer: umaEcosystem.timer,
                            spokePoolClient_1: spokePoolClient_1,
                            spokePoolClient_2: spokePoolClient_2,
                            spokePoolClient_3: spokePoolClient_3,
                            spokePoolClient_4: spokePoolClient_4,
                            spokePoolClients: spokePoolClients,
                            configStoreClient: configStoreClient,
                            mockedConfigStoreClient: configStoreClient,
                            hubPoolClient: hubPoolClient,
                            spyLogger: spyLogger,
                            spy: spy,
                            owner: owner,
                            depositor: depositor,
                            relayer: relayer,
                            dataworker: dataworker,
                            updateAllClients: function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
                                return tslib_1.__generator(this, function (_a) {
                                    switch (_a.label) {
                                        case 0: return [4, configStoreClient.update()];
                                        case 1:
                                            _a.sent();
                                            return [4, hubPoolClient.update()];
                                        case 2:
                                            _a.sent();
                                            return [4, spokePoolClient_1.update()];
                                        case 3:
                                            _a.sent();
                                            return [4, spokePoolClient_2.update()];
                                        case 4:
                                            _a.sent();
                                            return [4, spokePoolClient_3.update()];
                                        case 5:
                                            _a.sent();
                                            return [4, spokePoolClient_4.update()];
                                        case 6:
                                            _a.sent();
                                            return [2];
                                    }
                                });
                            }); },
                        }];
            }
        });
    });
}
function _constructSpokePoolClientsWithLookback(spokePools, spokePoolChains, spyLogger, signer, hubPoolClient, lookbackForAllChains, deploymentBlocks) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var latestBlocks;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4, hubPoolClient.update()];
                case 1:
                    _a.sent();
                    return [4, Promise.all(spokePools.map(function (x) { return x.provider.getBlockNumber(); }))];
                case 2:
                    latestBlocks = _a.sent();
                    return [2, spokePools.map(function (pool, i) {
                            var _a;
                            return new clients.EVMSpokePoolClient(spyLogger, pool.connect(signer), hubPoolClient, spokePoolChains[i], (_a = deploymentBlocks === null || deploymentBlocks === void 0 ? void 0 : deploymentBlocks[spokePoolChains[i]]) !== null && _a !== void 0 ? _a : 0, lookbackForAllChains === undefined ? undefined : { from: latestBlocks[i] - lookbackForAllChains });
                        })];
            }
        });
    });
}
function deployHubPool(ethers_1) {
    return tslib_1.__awaiter(this, arguments, void 0, function (ethers, spokePoolName) {
        var _a, signer, crossChainAdmin, parentFixture, weth, usdc, dai, usdt, tokens, lpTokenFactory, hubPool, mockAdapter, mockSpoke, _b, _c, mainnetChainId, mockAdapterMainnet, mockSpokeMainnet, _d, _e, l2UsdtContract, mockTokens;
        if (spokePoolName === void 0) { spokePoolName = "MockSpokePool"; }
        return tslib_1.__generator(this, function (_f) {
            switch (_f.label) {
                case 0: return [4, ethers.getSigners()];
                case 1:
                    _a = _f.sent(), signer = _a[0], crossChainAdmin = _a[1];
                    return [4, (0, UmaEcosystemFixture_1.setupUmaEcosystem)(signer)];
                case 2:
                    parentFixture = _f.sent();
                    return [4, (0, getContractFactory_1.getContractFactory)("WETH9", signer)];
                case 3: return [4, (_f.sent()).deploy()];
                case 4:
                    weth = _f.sent();
                    return [4, (0, getContractFactory_1.getContractFactory)("ExpandedERC20", signer)];
                case 5: return [4, (_f.sent()).deploy("USD Coin", "USDC", 6)];
                case 6:
                    usdc = _f.sent();
                    return [4, usdc.addMember(constants_1.TokenRolesEnum.MINTER, signer.address)];
                case 7:
                    _f.sent();
                    return [4, (0, getContractFactory_1.getContractFactory)("ExpandedERC20", signer)];
                case 8: return [4, (_f.sent()).deploy("DAI Stablecoin", "DAI", 18)];
                case 9:
                    dai = _f.sent();
                    return [4, dai.addMember(constants_1.TokenRolesEnum.MINTER, signer.address)];
                case 10:
                    _f.sent();
                    return [4, (0, getContractFactory_1.getContractFactory)("ExpandedERC20", signer)];
                case 11: return [4, (_f.sent()).deploy("USDT Stablecoin", "USDT", 6)];
                case 12:
                    usdt = _f.sent();
                    return [4, usdt.addMember(constants_1.TokenRolesEnum.MINTER, signer.address)];
                case 13:
                    _f.sent();
                    tokens = { weth: weth, usdc: usdc, dai: dai, usdt: usdt };
                    return [4, parentFixture.collateralWhitelist.addToWhitelist(weth.address)];
                case 14:
                    _f.sent();
                    return [4, parentFixture.collateralWhitelist.addToWhitelist(usdc.address)];
                case 15:
                    _f.sent();
                    return [4, parentFixture.collateralWhitelist.addToWhitelist(dai.address)];
                case 16:
                    _f.sent();
                    return [4, parentFixture.collateralWhitelist.addToWhitelist(usdt.address)];
                case 17:
                    _f.sent();
                    return [4, parentFixture.store.setFinalFee(weth.address, { rawValue: constants_1.finalFee })];
                case 18:
                    _f.sent();
                    return [4, parentFixture.store.setFinalFee(usdc.address, { rawValue: constants_1.finalFeeUsdc })];
                case 19:
                    _f.sent();
                    return [4, parentFixture.store.setFinalFee(dai.address, { rawValue: constants_1.finalFee })];
                case 20:
                    _f.sent();
                    return [4, parentFixture.store.setFinalFee(usdt.address, { rawValue: constants_1.finalFeeUsdt })];
                case 21:
                    _f.sent();
                    return [4, (0, getContractFactory_1.getContractFactory)("LpTokenFactory", signer)];
                case 22: return [4, (_f.sent()).deploy()];
                case 23:
                    lpTokenFactory = _f.sent();
                    return [4, (0, getContractFactory_1.getContractFactory)("HubPool", signer)];
                case 24: return [4, (_f.sent()).deploy(lpTokenFactory.address, parentFixture.finder.address, weth.address, parentFixture.timer.address)];
                case 25:
                    hubPool = _f.sent();
                    return [4, hubPool.setBond(weth.address, constants_1.bondAmount)];
                case 26:
                    _f.sent();
                    return [4, hubPool.setLiveness(7200)];
                case 27:
                    _f.sent();
                    return [4, (0, getContractFactory_1.getContractFactory)("Mock_Adapter", signer)];
                case 28: return [4, (_f.sent()).deploy()];
                case 29:
                    mockAdapter = _f.sent();
                    _c = (_b = hardhat_1.default.upgrades).deployProxy;
                    return [4, (0, getContractFactory_1.getContractFactory)(spokePoolName, signer)];
                case 30: return [4, _c.apply(_b, [_f.sent(), [0, crossChainAdmin.address, hubPool.address],
                        { kind: "uups", unsafeAllow: ["delegatecall"], constructorArgs: [weth.address] }])];
                case 31:
                    mockSpoke = _f.sent();
                    return [4, hubPool.setCrossChainContracts(constants_1.repaymentChainId, mockAdapter.address, mockSpoke.address)];
                case 32:
                    _f.sent();
                    return [4, hubPool.setCrossChainContracts(constants_1.originChainId, mockAdapter.address, mockSpoke.address)];
                case 33:
                    _f.sent();
                    return [4, hardhat_1.default.getChainId()];
                case 34:
                    mainnetChainId = _f.sent();
                    return [4, (0, getContractFactory_1.getContractFactory)("Mock_Adapter", signer)];
                case 35: return [4, (_f.sent()).deploy()];
                case 36:
                    mockAdapterMainnet = _f.sent();
                    _e = (_d = hardhat_1.default.upgrades).deployProxy;
                    return [4, (0, getContractFactory_1.getContractFactory)(spokePoolName, signer)];
                case 37: return [4, _e.apply(_d, [_f.sent(), [0, crossChainAdmin.address, hubPool.address],
                        { kind: "uups", unsafeAllow: ["delegatecall"], constructorArgs: [weth.address] }])];
                case 38:
                    mockSpokeMainnet = _f.sent();
                    return [4, hubPool.setCrossChainContracts(mainnetChainId, mockAdapterMainnet.address, mockSpokeMainnet.address)];
                case 39:
                    _f.sent();
                    return [4, (0, getContractFactory_1.getContractFactory)("ExpandedERC20", signer)];
                case 40: return [4, (_f.sent()).deploy("USDT Stablecoin", "USDT", 6)];
                case 41:
                    l2UsdtContract = _f.sent();
                    return [4, l2UsdtContract.addMember(constants_1.TokenRolesEnum.MINTER, signer.address)];
                case 42:
                    _f.sent();
                    mockTokens = {
                        l2Weth: (0, constants_1.randomAddress)(),
                        l2Dai: (0, constants_1.randomAddress)(),
                        l2Usdc: (0, constants_1.randomAddress)(),
                        l2Usdt: l2UsdtContract.address,
                    };
                    return [4, hubPool.setPoolRebalanceRoute(constants_1.repaymentChainId, weth.address, mockTokens.l2Weth)];
                case 43:
                    _f.sent();
                    return [4, hubPool.setPoolRebalanceRoute(constants_1.repaymentChainId, dai.address, mockTokens.l2Dai)];
                case 44:
                    _f.sent();
                    return [4, hubPool.setPoolRebalanceRoute(constants_1.repaymentChainId, usdc.address, mockTokens.l2Usdc)];
                case 45:
                    _f.sent();
                    return [4, hubPool.setPoolRebalanceRoute(constants_1.repaymentChainId, usdt.address, mockTokens.l2Usdt)];
                case 46:
                    _f.sent();
                    return [2, tslib_1.__assign(tslib_1.__assign(tslib_1.__assign(tslib_1.__assign(tslib_1.__assign({}, tokens), { l2UsdtContract: l2UsdtContract }), mockTokens), { hubPool: hubPool, mockAdapter: mockAdapter, mockSpoke: mockSpoke, crossChainAdmin: crossChainAdmin }), parentFixture)];
            }
        });
    });
}
exports.hubPoolFixture = hardhat_1.default.deployments.createFixture(function (_a) { return tslib_1.__awaiter(void 0, [_a], void 0, function (_b) {
    var ethers = _b.ethers;
    return tslib_1.__generator(this, function (_c) {
        switch (_c.label) {
            case 0: return [4, deployHubPool(ethers)];
            case 1: return [2, _c.sent()];
        }
    });
}); });
function enableTokensForLP(owner, hubPool, _weth, tokens) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var lpTokens, _i, tokens_1, token, pooledTokens, _a, _b;
        return tslib_1.__generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    lpTokens = [];
                    _i = 0, tokens_1 = tokens;
                    _c.label = 1;
                case 1:
                    if (!(_i < tokens_1.length)) return [3, 7];
                    token = tokens_1[_i];
                    return [4, hubPool.enableL1TokenForLiquidityProvision(token.address)];
                case 2:
                    _c.sent();
                    return [4, hubPool.callStatic.pooledTokens(token.address)];
                case 3:
                    pooledTokens = _c.sent();
                    _b = (_a = lpTokens).push;
                    return [4, (0, getContractFactory_1.getContractFactory)("ExpandedERC20", owner)];
                case 4: return [4, (_c.sent()).attach(pooledTokens.lpToken)];
                case 5:
                    _b.apply(_a, [_c.sent()]);
                    _c.label = 6;
                case 6:
                    _i++;
                    return [3, 1];
                case 7: return [2, lpTokens];
            }
        });
    });
}
//# sourceMappingURL=HubPool.Fixture.js.map