"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 getContract_1 = require("../../../../utils/solidity/getContract");
const deployContract_1 = require("../../../../utils/solidity/deployContract");
const emptyAddress_1 = require("../../../../utils/constants/emptyAddress");
const randomAddress_1 = require("../../../../utils/helpers/randomAddress");
const token_math_1 = require("@melonproject/token-math");
describe('trading', () => {
    let shared = {};
    // Mock data
    const mockExchanges = [
        randomAddress_1.randomAddress().toString(),
        randomAddress_1.randomAddress().toString(),
    ];
    const mockExchangeAdapters = [
        randomAddress_1.randomAddress().toString(),
        randomAddress_1.randomAddress().toString(),
    ];
    const takesCustodyMasks = [true, false];
    beforeAll(() => __awaiter(this, void 0, void 0, function* () {
        shared.env = yield initTestEnvironment_1.initTestEnvironment();
        shared = Object.assign(shared, yield deployMockSystem_1.deployMockSystem(shared.env));
        shared.user = shared.env.wallet.address;
        for (let i = 0; i < mockExchanges.length; i = i + 1) {
            yield shared.registry.methods
                .registerAdapterForExchange(mockExchanges[i], mockExchangeAdapters[i])
                .send({ from: shared.user });
        }
        shared.trading = getContract_1.getContract(shared.env, Contracts_1.Contracts.Trading, yield deployContract_1.deployContract(shared.env, Contracts_1.Contracts.Trading, [
            shared.hub.options.address,
            mockExchanges,
            mockExchangeAdapters,
            takesCustodyMasks,
            shared.registry.options.address,
        ]));
        yield shared.hub.methods
            .setSpokes([
            emptyAddress_1.emptyAddress,
            emptyAddress_1.emptyAddress,
            emptyAddress_1.emptyAddress,
            emptyAddress_1.emptyAddress,
            emptyAddress_1.emptyAddress,
            emptyAddress_1.emptyAddress,
            shared.vault.options.address,
            emptyAddress_1.emptyAddress,
            emptyAddress_1.emptyAddress,
            emptyAddress_1.emptyAddress,
            emptyAddress_1.emptyAddress,
            emptyAddress_1.emptyAddress,
        ])
            .send({ from: shared.user, gas: 8000000 });
        yield shared.hub.methods
            .initializeSpoke(shared.trading.options.address)
            .send({ from: shared.user, gas: 8000000 });
    }));
    it('Exchanges are properly initialized', () => __awaiter(this, void 0, void 0, function* () {
        for (const i of Array.from(Array(mockExchanges.length).keys())) {
            const exchangeObject = yield shared.trading.methods.exchanges(i).call();
            expect(exchangeObject.exchange).toBe(mockExchanges[i]);
            expect(exchangeObject.adapter).toBe(mockExchangeAdapters[i]);
            expect(exchangeObject.takesCustody).toBe(takesCustodyMasks[i]);
            const exchangeAdded = yield shared.trading.methods
                .exchangeIsAdded(mockExchanges[i])
                .call();
            expect(exchangeAdded).toBe(true);
        }
    }));
    it('Exchanges cannot be initialized without its adapter', () => __awaiter(this, void 0, void 0, function* () {
        const errorMessage = 'Array lengths unequal';
        yield expect(deployContract_1.deployContract(shared.env, Contracts_1.Contracts.Trading, [
            shared.hub.options.address,
            mockExchanges,
            [mockExchangeAdapters[0]],
            takesCustodyMasks,
            shared.registry.options.address,
        ])).rejects.toThrow(errorMessage);
    }));
    it('returnBatchToVault sends back token balances to the vault', () => __awaiter(this, void 0, void 0, function* () {
        const tokenQuantity = new token_math_1.BigInteger(Math.pow(10, 20));
        yield shared.mln.methods
            .transfer(shared.trading.options.address, `${tokenQuantity}`)
            .send({ from: shared.user, gas: 8000000 });
        yield shared.weth.methods
            .transfer(shared.trading.options.address, `${tokenQuantity}`)
            .send({ from: shared.user, gas: 8000000 });
        const preMlnVault = new token_math_1.BigInteger(yield shared.mln.methods.balanceOf(shared.vault.options.address).call());
        const preWethVault = new token_math_1.BigInteger(yield shared.weth.methods.balanceOf(shared.vault.options.address).call());
        yield shared.trading.methods
            .returnBatchToVault([
            shared.mln.options.address,
            shared.weth.options.address,
        ])
            .send({ from: shared.user, gas: 8000000 });
        const postMlnTrading = new token_math_1.BigInteger(yield shared.mln.methods.balanceOf(shared.trading.options.address).call());
        const postWethTrading = new token_math_1.BigInteger(yield shared.weth.methods
            .balanceOf(shared.trading.options.address)
            .call());
        const postMlnVault = new token_math_1.BigInteger(yield shared.mln.methods.balanceOf(shared.vault.options.address).call());
        const postWethVault = new token_math_1.BigInteger(yield shared.weth.methods.balanceOf(shared.vault.options.address).call());
        expect(token_math_1.isEqual(postMlnTrading, new token_math_1.BigInteger(0))).toBe(true);
        expect(token_math_1.isEqual(postWethTrading, new token_math_1.BigInteger(0))).toBe(true);
        expect(token_math_1.isEqual(postMlnVault, token_math_1.add(preMlnVault, tokenQuantity))).toBe(true);
        expect(token_math_1.isEqual(postWethVault, token_math_1.add(preWethVault, tokenQuantity))).toBe(true);
    }));
});
