"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 Contracts_1 = require("../../../../Contracts");
const initTestEnvironment_1 = require("../../../../tests/utils/initTestEnvironment");
const deployMockSystem_1 = require("../../../../utils/deploy/deployMockSystem");
const token_math_1 = require("@melonproject/token-math");
describe('accounting', () => {
    let shared = {};
    beforeAll(() => __awaiter(this, void 0, void 0, function* () {
        shared.env = yield initTestEnvironment_1.initTestEnvironment();
        shared = Object.assign({}, shared, (yield deployMockSystem_1.deployMockSystem(shared.env, {
            accountingContract: Contracts_1.Contracts.Accounting,
        })));
        shared.user = shared.env.wallet.address;
        shared.mockDefaultAssets = [
            shared.weth.options.address,
            shared.mln.options.address,
        ];
        shared.mockQuoteAsset = shared.weth.options.address;
        shared.mockNativeAsset = shared.weth.options.address;
        shared.exaUnit = new token_math_1.BigInteger('1000000000000000000');
    }));
    it('Accounting is properly initialized', () => __awaiter(this, void 0, void 0, function* () {
        for (const i of Array.from(Array(shared.mockDefaultAssets.length).keys())) {
            const defaultAsset = yield shared.accounting.methods
                .ownedAssets(i)
                .call();
            expect(defaultAsset).toBe(shared.mockDefaultAssets[i]);
            yield expect(shared.accounting.methods
                .isInAssetList(shared.mockDefaultAssets[i])
                .call()).resolves.toBe(true);
        }
        yield expect(shared.accounting.methods.DENOMINATION_ASSET().call()).resolves.toBe(shared.mockQuoteAsset);
        yield expect(shared.accounting.methods.NATIVE_ASSET().call()).resolves.toBe(shared.mockNativeAsset);
        yield expect(shared.accounting.methods.calcSharePrice().call()).resolves.toBe(`${shared.exaUnit}`);
        yield expect(shared.accounting.methods.calcGav().call()).resolves.toBe('0');
        const initialCalculations = yield shared.accounting.methods
            .performCalculations()
            .call();
        expect(initialCalculations.gav).toBe('0');
        expect(initialCalculations.feesInDenominationAsset).toBe('0');
        expect(initialCalculations.feesInShares).toBe('0');
        expect(initialCalculations.nav).toBe('0');
        expect(initialCalculations.sharePrice).toBe(`${shared.exaUnit}`);
    }));
    it('updateOwnedAssets removes zero balance assets', () => __awaiter(this, void 0, void 0, function* () {
        const fundHoldings = yield shared.accounting.methods
            .getFundHoldings()
            .call();
        expect(fundHoldings[0]).toEqual(Array.from(Array(shared.mockDefaultAssets.length), () => '0'));
        yield shared.accounting.methods
            .updateOwnedAssets()
            .send({ from: shared.user, gas: 8000000 });
        for (const i of Array.from(Array(shared.mockDefaultAssets.length).keys())) {
            if (shared.mockDefaultAssets[i] === shared.mockQuoteAsset)
                continue;
            yield expect(shared.accounting.methods
                .isInAssetList(shared.mockDefaultAssets[i])
                .call()).resolves.toBe(false);
        }
    }));
    it('Balance in vault reflects in accounting', () => __awaiter(this, void 0, void 0, function* () {
        const tokenQuantity = `${'10000000000000000000'}`;
        yield shared.weth.methods
            .transfer(shared.vault.options.address, tokenQuantity)
            .send({ from: shared.user, gas: 8000000 });
        const fundHoldings = yield shared.accounting.methods
            .getFundHoldings()
            .call();
        expect(fundHoldings[0][0]).toEqual(tokenQuantity);
        yield shared.priceSource.methods
            .update([shared.weth.options.address], [`${shared.exaUnit}`])
            .send({ from: shared.user, gas: 8000000 });
        const initialCalculations = yield shared.accounting.methods
            .performCalculations()
            .call();
        expect(initialCalculations.gav).toBe(tokenQuantity);
        expect(initialCalculations.feesInDenominationAsset).toBe('0');
        expect(initialCalculations.feesInShares).toBe('0');
        expect(initialCalculations.nav).toBe(tokenQuantity);
        // Since there is no investment yet
        expect(initialCalculations.sharePrice).toBe(`${shared.exaUnit}`);
    }));
    // Deployer is an authorized module because it has been directly deployed
    it('Add and remove assets by an authorized module', () => __awaiter(this, void 0, void 0, function* () {
        yield expect(shared.accounting.methods
            .isInAssetList(shared.mln.options.address)
            .call()).resolves.toBe(false);
        yield shared.accounting.methods
            .addAssetToOwnedAssets(shared.mln.options.address)
            .send({ from: shared.user, gas: 8000000 });
        yield expect(shared.accounting.methods
            .isInAssetList(shared.mln.options.address)
            .call()).resolves.toBe(true);
        yield shared.accounting.methods
            .removeFromOwnedAssets(shared.mln.options.address)
            .send({ from: shared.user, gas: 8000000 });
        yield expect(shared.accounting.methods
            .isInAssetList(shared.mln.options.address)
            .call()).resolves.toBe(false);
    }));
});
