"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 token_math_1 = require("@melonproject/token-math");
const getContract_1 = require("../solidity/getContract");
const deploy_1 = require("../../contracts/dependencies/token/transactions/deploy");
const getToken_1 = require("../../contracts/dependencies/token/calls/getToken");
const deployMatchingMarket_1 = require("../../contracts/exchanges/transactions/deployMatchingMarket");
const deployKyberEnvironment_1 = require("../../contracts/exchanges/transactions/deployKyberEnvironment");
const deploy0xExchange_1 = require("../../contracts/exchanges/transactions/deploy0xExchange");
const deployEthfinex_1 = require("../../contracts/exchanges/transactions/deployEthfinex");
const ensure_1 = require("../guards/ensure");
const Contracts_1 = require("../../Contracts");
const deployThirdParty = (environment, tokens = [
    token_math_1.createToken('WETH'),
    token_math_1.createToken('MLN'),
    token_math_1.createToken('EUR'),
    token_math_1.createToken('DGX', undefined, 9),
    token_math_1.createToken('ZRX'),
]) => __awaiter(this, void 0, void 0, function* () {
    ensure_1.ensure(!!tokens.find(t => t.symbol === 'WETH'), 'WETH Token is required');
    ensure_1.ensure(!!tokens.find(t => t.symbol === 'MLN'), 'MLN Token is required');
    ensure_1.ensure(!!tokens.find(t => t.symbol === 'EUR'), 'EUR Token is required');
    ensure_1.ensure(!!tokens.find(t => t.symbol === 'DGX'), 'DGX Token is required');
    ensure_1.ensure(!!tokens.find(t => t.symbol === 'ZRX'), 'ZRX Token is required');
    // : Promise<thirdPartyContracts>
    const deployedTokens = yield tokens.reduce((carryP, current) => __awaiter(this, void 0, void 0, function* () {
        const carry = yield carryP;
        let deployed;
        if (current.symbol === 'WETH') {
            deployed = yield getToken_1.getToken(environment, yield deploy_1.deployWeth(environment));
        }
        else {
            deployed = yield getToken_1.getToken(environment, yield deploy_1.deployToken(environment, current.symbol, current.decimals));
        }
        return [...carry, deployed];
    }), Promise.resolve([]));
    // Deposit WETH
    const depositAmount = token_math_1.power(new token_math_1.BigInteger(10), new token_math_1.BigInteger(24));
    yield getContract_1.getContract(environment, Contracts_1.Contracts.Weth, deployedTokens.find(t => t.symbol === 'WETH').address)
        .methods.deposit()
        .send({
        from: environment.wallet.address,
        value: `${depositAmount}`,
    });
    const zrxToken = deployedTokens.find(t => t.symbol === 'ZRX');
    const matchingMarket = yield deployMatchingMarket_1.deployMatchingMarket(environment, {
        tokens: deployedTokens,
    });
    const kyber = yield deployKyberEnvironment_1.deployKyberEnvironment(environment, [
        deployedTokens.find(t => t.symbol === 'MLN'),
        deployedTokens.find(t => t.symbol === 'EUR'),
    ]);
    const zeroEx = yield deploy0xExchange_1.deploy0xExchange(environment, { zrxToken });
    const ethfinex = yield deployEthfinex_1.deployEthfinex(environment, {
        tokens: deployedTokens,
    });
    return {
        exchanges: {
            ethfinex,
            kyber,
            matchingMarket,
            zeroEx,
        },
        tokens: deployedTokens,
    };
});
exports.deployThirdParty = deployThirdParty;
