"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 randomAddress_1 = require("../../../../utils/helpers/randomAddress");
const deployMockSystem_1 = require("../../../../utils/deploy/deployMockSystem");
const Contracts_1 = require("../../../../Contracts");
const Environment_1 = require("../../../../utils/environment/Environment");
describe('redemption', () => {
    let debug;
    const shared = {};
    beforeAll(() => __awaiter(this, void 0, void 0, function* () {
        shared.env = yield initTestEnvironment_1.initTestEnvironment();
        debug = shared.env.logger('melon:protocol:test:redemption', Environment_1.LogLevels.DEBUG);
        shared.mockDeploy = yield deployMockSystem_1.deployMockSystem(shared.env, {
            accountingContract: Contracts_1.Contracts.Accounting,
        });
        debug('mockDeploy', Object.keys(shared.mockDeploy));
        shared.user = shared.env.wallet.address;
    }));
    it('Redeem with no shares fails', () => __awaiter(this, void 0, void 0, function* () {
        const errorMessage = 'Sender does not have enough shares to fulfill request';
        const preShares = yield shared.mockDeploy.shares.methods
            .balanceOf(shared.user)
            .call();
        yield shared.mockDeploy.shares.methods
            .createFor(`${randomAddress_1.randomAddress()}`, '1000')
            .send({ from: shared.user });
        expect(preShares).toBe('0');
        yield expect(shared.mockDeploy.participation.methods
            .redeem()
            .send({ from: shared.user, gas: 8000000 })).rejects.toThrow(errorMessage);
        yield expect(shared.mockDeploy.participation.methods
            .redeemWithConstraints('1', [])
            .send({ from: shared.user, gas: 8000000 })).rejects.toThrow(errorMessage);
    }));
    it('Asset not in list prevents redemption', () => __awaiter(this, void 0, void 0, function* () {
        const errorMessage = 'Requested asset not in asset list';
        const addr = `${randomAddress_1.randomAddress()}`;
        yield shared.mockDeploy.shares.methods
            .createFor(`${shared.user}`, '1000')
            .send({ from: shared.user });
        const preShares = yield shared.mockDeploy.shares.methods
            .balanceOf(shared.user)
            .call();
        yield expect(shared.mockDeploy.participation.methods
            .redeemWithConstraints('1', [addr])
            .send({ from: shared.user, gas: 8000000 })).rejects.toThrow(errorMessage);
        const postShares = yield shared.mockDeploy.shares.methods
            .balanceOf(shared.user)
            .call();
        expect(preShares).toBe(postShares);
    }));
    it('Asset cannot be redeemed twice', () => __awaiter(this, void 0, void 0, function* () {
        const errorMessage = 'Asset can only be redeemed once';
        const preShares = yield shared.mockDeploy.shares.methods
            .balanceOf(shared.user)
            .call();
        yield expect(shared.mockDeploy.participation.methods
            .redeemWithConstraints('1', [
            shared.mockDeploy.weth.options.address,
            shared.mockDeploy.weth.options.address,
        ])
            .send({ from: shared.user, gas: 8000000 })).rejects.toThrow(errorMessage);
        const postShares = yield shared.mockDeploy.shares.methods
            .balanceOf(shared.user)
            .call();
        expect(preShares).toBe(postShares);
    }));
    it('Vault-held assets can be redeemed', () => __awaiter(this, void 0, void 0, function* () {
        const wethAmount = '1000';
        yield shared.mockDeploy.weth.methods
            .transfer(shared.mockDeploy.vault.options.address, wethAmount)
            .send({ from: shared.user });
        const heldWeth = yield shared.mockDeploy.accounting.methods
            .assetHoldings(shared.mockDeploy.weth.options.address)
            .call();
        const preShares = yield shared.mockDeploy.shares.methods
            .balanceOf(shared.user)
            .call();
        expect(heldWeth).toBe(wethAmount);
        yield shared.mockDeploy.participation.methods
            .redeemWithConstraints(preShares, [
            shared.mockDeploy.weth.options.address,
        ])
            .send({ from: shared.user, gas: 8000000 });
        const postShares = yield shared.mockDeploy.shares.methods
            .balanceOf(shared.user)
            .call();
        expect(postShares).toBe('0');
    }));
});
