"use strict";
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());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSwapParam = exports.getSCYHarvestParams = exports.maxHarvestGasPrice = exports.minTvl = void 0;
var ethers_1 = require("ethers");
var utils_1 = require("../utils");
exports.minTvl = {
    '0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664': 10,
    '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75': 10, // ftm usdc
};
var maxHarvestGasPrice = function (chain) {
    switch (chain) {
        case 'avalanche':
            return 3 * 30e9;
        case 'fantom':
            return 3 * 500e9;
        case 'moonriver':
            return 3 * 2e9;
        default:
            return 999e9;
    }
};
exports.maxHarvestGasPrice = maxHarvestGasPrice;
var getSCYHarvestParams = function (scyVault, strat, signer, deadline, // 1 h deadline default
skipMinCheck, revertOnError
// ignoreSlippage = false
) {
    if (deadline === void 0) { deadline = Math.round(Date.now() / 1000 + 60 * 60 * 1); }
    if (skipMinCheck === void 0) { skipMinCheck = false; }
    if (revertOnError === void 0) { revertOnError = false; }
    return __awaiter(void 0, void 0, void 0, function () {
        var lendRewardPath, harvestPath, tvl, delta, swapParams1, swapParams2, farmHarvests, lendHarvest, err_1, err_2, farmHarvest;
        var _a, _b, _c;
        return __generator(this, function (_d) {
            switch (_d.label) {
                case 0:
                    lendRewardPath = strat.lendRewardPath, harvestPath = strat.harvestPath;
                    scyVault = scyVault.connect(signer);
                    return [4 /*yield*/, scyVault.getTvl()];
                case 1:
                    tvl = _d.sent();
                    delta = tvl.div(200);
                    if (harvestPath == null && lendRewardPath == null)
                        return [2 /*return*/, {
                                harvestArgs: [tvl, delta, [], []],
                                farmHarvest: utils_1.BigNumber.from(0),
                                lendHarvest: utils_1.BigNumber.from(0),
                            }];
                    // TODO config harvest path vs harvest pairs
                    // harvestPaths is an array of uniswapV3 paths
                    if (strat.harvestPaths != null) {
                        swapParams1 = strat.harvestPaths.map(function (path) {
                            return (0, exports.getSwapParam)(path, 0, deadline);
                        });
                    }
                    else
                        swapParams1 =
                            harvestPath == null ? [] : [(0, exports.getSwapParam)(harvestPath, 0, deadline)];
                    swapParams2 = lendRewardPath == null ? [] : [(0, exports.getSwapParam)(lendRewardPath, 0, deadline)];
                    farmHarvests = [];
                    lendHarvest = utils_1.BigNumber.from(0);
                    _d.label = 2;
                case 2:
                    _d.trys.push([2, 5, , 6]);
                    if (!(swapParams1 === null || swapParams1 === void 0 ? void 0 : swapParams1.length)) return [3 /*break*/, 4];
                    console.log('static call1');
                    return [4 /*yield*/, scyVault.callStatic.harvest(tvl, delta, swapParams1, [])];
                case 3:
                    _a = __read.apply(void 0, [_d.sent(), 1]), farmHarvests = _a[0];
                    _d.label = 4;
                case 4: return [3 /*break*/, 6];
                case 5:
                    err_1 = _d.sent();
                    console.error('static call error', err_1);
                    if (revertOnError) {
                        console.error('COULD NOT HARVEST', strat.name);
                        throw err_1;
                    }
                    return [3 /*break*/, 6];
                case 6:
                    _d.trys.push([6, 9, , 10]);
                    if (!swapParams2.length) return [3 /*break*/, 8];
                    console.log('static call2');
                    return [4 /*yield*/, scyVault.callStatic.harvest(tvl, delta, [], swapParams2)];
                case 7:
                    _b = __read.apply(void 0, [_d.sent(), 2]), _c = __read(_b[1], 1), lendHarvest = _c[0];
                    _d.label = 8;
                case 8: return [3 /*break*/, 10];
                case 9:
                    err_2 = _d.sent();
                    // don't revert here
                    console.log('static call 2 error', err_2);
                    return [3 /*break*/, 10];
                case 10:
                    farmHarvest = farmHarvests === null || farmHarvests === void 0 ? void 0 : farmHarvests.reduce(function (a, h) { return a.add(h); }, utils_1.BigNumber.from(0));
                    console.log('farmHarvest', farmHarvests === null || farmHarvests === void 0 ? void 0 : farmHarvests.map(function (h) { return h.toString(); }), farmHarvest.toString());
                    console.log('lendHarvest', lendHarvest === null || lendHarvest === void 0 ? void 0 : lendHarvest.toString());
                    swapParams1 = swapParams1.filter(function (p, i) { var _a; return (_a = farmHarvests[i]) === null || _a === void 0 ? void 0 : _a.gt(0); });
                    swapParams1.forEach(function (p, i) { return (p.min = farmHarvests[i].mul(9990).div(10000)); });
                    if (!(lendHarvest === null || lendHarvest === void 0 ? void 0 : lendHarvest.gt(0)))
                        swapParams2 = [];
                    else
                        swapParams2[0].min = lendHarvest.mul(9990).div(10000);
                    // TODO compare gas cost of farmHarvest vs gas costs
                    return [2 /*return*/, {
                            harvestArgs: [tvl, delta, swapParams1, swapParams2],
                            farmHarvest: farmHarvest,
                            lendHarvest: lendHarvest,
                        }];
            }
        });
    });
};
exports.getSCYHarvestParams = getSCYHarvestParams;
var getSwapParam = function (harvestPath, min, deadline) {
    var path = typeof harvestPath === 'string' ? [] : harvestPath;
    var pathData = typeof harvestPath === 'string' ? harvestPath : ethers_1.constants.HashZero;
    return {
        path: path,
        min: min,
        deadline: deadline,
        pathData: pathData,
    };
};
exports.getSwapParam = getSwapParam;
//# sourceMappingURL=harvestParams.js.map