"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const initTestEnvironment_1 = require("../../../../tests/utils/initTestEnvironment");
const deployMockSystem_1 = require("../../../../utils/deploy/deployMockSystem");
const randomAddress_1 = require("../../../../utils/helpers/randomAddress");
const Contracts_1 = require("../../../../Contracts");
const increaseTime_1 = require("../../../../utils/evm/increaseTime");
const weekInSeconds = 60 * 60 * 24 * 7;
describe('investment', () => {
    let shared = {};
    beforeAll(() => __awaiter(this, void 0, void 0, function* () {
        shared.env = yield initTestEnvironment_1.initTestEnvironment();
        shared.user = shared.env.wallet.address;
        shared = Object.assign(shared, yield deployMockSystem_1.deployMockSystem(shared.env, {
            accountingContract: Contracts_1.Contracts.Accounting,
        }));
        const price = '1000000000000000000';
        yield shared.priceSource.methods
            .update([shared.weth.options.address, shared.mln.options.address], [price, price])
            .send({ from: shared.user, gas: 8000000 });
        yield shared.registry.methods
            .setIsFund(shared.participation.options.address)
            .send({ from: shared.user });
    }));
    it('Invest fails in shut down fund', () => __awaiter(this, void 0, void 0, function* () {
        const errorMessage = 'Hub is shut down';
        const amount = '1000000000000000000';
        yield shared.hub.methods.setShutDownState(true).send({ from: shared.user });
        yield expect(shared.participation.methods
            .requestInvestment(amount, amount, shared.weth.options.address)
            .send({ from: shared.user, gas: 8000000 })).rejects.toThrow(errorMessage);
        yield shared.hub.methods
            .setShutDownState(false)
            .send({ from: shared.user });
        yield shared.weth.methods
            .approve(shared.participation.options.address, amount)
            .send({ from: shared.user });
        yield shared.participation.methods
            .requestInvestment(amount, amount, shared.weth.options.address)
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) });
        yield shared.hub.methods.setShutDownState(true).send({ from: shared.user });
        yield expect(shared.participation.methods
            .executeRequestFor(shared.user)
            .send({ from: shared.user, gas: 8000000 })).rejects.toThrow(errorMessage);
        yield shared.hub.methods
            .setShutDownState(false)
            .send({ from: shared.user });
        yield increaseTime_1.increaseTime(shared.env, weekInSeconds);
        yield shared.participation.methods
            .cancelRequest()
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) });
    }));
    it('Request must exist to execute', () => __awaiter(this, void 0, void 0, function* () {
        const errorMessage = 'No valid request for this address';
        const requestExists = yield shared.participation.methods
            .hasRequest(shared.user)
            .call();
        expect(requestExists).toBe(false);
        yield expect(shared.participation.methods
            .executeRequestFor(shared.user)
            .send({ from: shared.user, gas: 8000000 })).rejects.toThrow(errorMessage);
        yield shared.participation.methods
            .requestInvestment(0, 0, shared.weth.options.address)
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) });
        yield expect(shared.participation.methods
            .executeRequestFor(shared.user)
            .send({ from: shared.user, gas: 8000000 })).rejects.toThrow(errorMessage);
        yield increaseTime_1.increaseTime(shared.env, weekInSeconds);
        yield shared.participation.methods
            .cancelRequest()
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) });
    }));
    it('Need fresh price to execute request', () => __awaiter(this, void 0, void 0, function* () {
        const errorMessage = 'Price not valid';
        const amount = '1000000000000000000';
        yield shared.priceSource.methods
            .setNeverValid(true)
            .send({ from: shared.user });
        yield shared.weth.methods
            .approve(shared.participation.options.address, amount)
            .send({ from: shared.user });
        yield shared.participation.methods
            .requestInvestment(amount, amount, shared.weth.options.address)
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) });
        const requestExists = yield shared.participation.methods
            .hasRequest(shared.user)
            .call();
        expect(requestExists).toBe(true);
        yield expect(shared.participation.methods
            .executeRequestFor(shared.user)
            .send({ from: shared.user, gas: 8000000 })).rejects.toThrow(errorMessage);
        yield shared.priceSource.methods
            .setNeverValid(false)
            .send({ from: shared.user });
        yield increaseTime_1.increaseTime(shared.env, weekInSeconds);
        yield shared.participation.methods
            .cancelRequest()
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) });
    }));
    it('Asset must be permitted', () => __awaiter(this, void 0, void 0, function* () {
        const errorMessage = 'Investment not allowed in this asset';
        const asset = `${randomAddress_1.randomAddress()}`;
        const amount = '100';
        const allowed = yield shared.participation.methods
            .investAllowed(asset)
            .call();
        expect(allowed).toBe(false);
        yield expect(shared.participation.methods
            .requestInvestment(amount, amount, asset)
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) })).rejects.toThrow(errorMessage);
    }));
    it('Invested amount must be above price minimum', () => __awaiter(this, void 0, void 0, function* () {
        const errorMessage = 'Invested amount too low';
        const price = '1000000000000000000';
        yield shared.priceSource.methods
            .update([shared.weth.options.address, shared.mln.options.address], [price, price])
            .send({ from: shared.user, gas: 8000000 });
        yield shared.weth.methods
            .approve(shared.participation.options.address, '1000')
            .send({ from: shared.user });
        yield shared.participation.methods
            .requestInvestment('1000', '1', shared.weth.options.address)
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) });
        yield expect(shared.participation.methods
            .executeRequestFor(shared.user)
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) })).rejects.toThrow(errorMessage);
        yield increaseTime_1.increaseTime(shared.env, weekInSeconds);
        yield shared.participation.methods
            .cancelRequest()
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) });
    }));
    it('Basic investment works', () => __awaiter(this, void 0, void 0, function* () {
        const investAmount = '1000';
        const sharesAmount = '1000';
        const preVaultWeth = yield shared.weth.methods
            .balanceOf(shared.vault.options.address)
            .call();
        yield shared.weth.methods
            .approve(shared.participation.options.address, investAmount)
            .send({ from: shared.user });
        yield shared.participation.methods
            .requestInvestment(sharesAmount, investAmount, shared.weth.options.address)
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) });
        yield shared.participation.methods
            .executeRequestFor(shared.user)
            .send({ from: shared.user, gas: 8000000, value: Math.pow(10, 16) });
        const postVaultWeth = yield shared.weth.methods
            .balanceOf(shared.vault.options.address)
            .call();
        const postShares = yield shared.shares.methods
            .balanceOf(shared.user)
            .call();
        const postSupply = yield shared.shares.methods.totalSupply().call();
        expect(postShares).toEqual(sharesAmount);
        expect(postSupply).toEqual(sharesAmount);
        expect(Number(postVaultWeth)).toEqual(Number(preVaultWeth) + Number(investAmount));
    }));
});
