"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const math_1 = require("../../test/resources/math");
const examples_1 = require("../../test/resources/examples");
const utilities_1 = require("../../test/utilities");
const util_1 = require("../util");
const logging_1 = require("../../src/logging");
const log = logging_1.factory.getLogger("scripts.setup_thegraph");
module.exports = function (callback) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const exchange = yield util_1.getBatchExchange(artifacts);
            const owl = yield util_1.getOwl(artifacts);
            log.info(`OWL address ${owl.address}`);
            // Prepare user accounts
            const [user1Address, user2Address] = yield web3.eth.getAccounts();
            const userAddresses = [user1Address, user2Address];
            const solverAddress = user2Address;
            const minter = user1Address;
            // Get current batch id
            let batchId = yield util_1.getBatchId(exchange);
            log.info(`Current batchId: ${batchId}`);
            // Set user1 as minter of OWL
            yield owl.setMinter(minter);
            // Mint OWL for every user
            const amount = web3.utils.toWei("3000");
            yield util_1.mintOwl(owl, userAddresses, amount, minter);
            // Create 1 token
            const token1Instance = yield util_1.createMintableToken(artifacts);
            const tokensInstances = [token1Instance];
            // Set allowances for OWL and the tokens
            yield util_1.setAllowances(userAddresses, amount, exchange, [owl]);
            yield util_1.setAllowances(userAddresses, amount, exchange, tokensInstances);
            // List the tokens in the exchange
            const tokenAddresses = [token1Instance.address];
            const [token1] = yield util_1.addTokens(tokenAddresses, user1Address, exchange, owl);
            // Mint tokens for all users
            yield util_1.mintTokens(tokensInstances, userAddresses, amount, minter);
            // Make deposits, place orders and close auction [aka runAuctionScenario(basicTrade)]
            yield utilities_1.makeDeposits(exchange, userAddresses, examples_1.basicTrade.deposits);
            // Place orders
            let orderIds = yield utilities_1.placeOrders(exchange, userAddresses, examples_1.basicTrade.orders, batchId + 1);
            // Request withdraw
            log.info(`Request withdraw for user ${user1Address}, token ${token1.address} (${token1.id})`);
            yield exchange.requestWithdraw(token1.address, 5, {
                from: user1Address,
            });
            // Close the auction
            log.info("Closing auction so we can withdraw the tokens");
            yield utilities_1.closeAuction(exchange, web3);
            // Withdraw tokens
            log.info(`Withdraw for user ${user1Address}, token ${token1.address} (${token1.id})`);
            yield exchange.withdraw(user1Address, token1.address, {
                from: user1Address,
            });
            // Submit solution
            yield util_1.submitSolution("Full solution", batchId, examples_1.solutionSubmissionParams(examples_1.basicTrade.solutions[0], userAddresses, orderIds), solverAddress, exchange);
            // Close auction
            log.info("Close auction after solution has been applied");
            yield utilities_1.closeAuction(exchange, web3);
            // Cancel the 2 orders
            log.info("Cancel the two orders");
            yield util_1.deleteOrders(orderIds, userAddresses, exchange);
            // Create a new order with validity only for next batch
            batchId = yield util_1.getBatchId(exchange);
            const newOrder = {
                sellToken: 0,
                buyToken: token1.id,
                sellAmount: math_1.toETH(10),
                buyAmount: math_1.toETH(10),
                user: 0,
            };
            log.info(`Place new order: ${JSON.stringify(newOrder)}`);
            orderIds = yield utilities_1.placeOrders(exchange, [user1Address], [newOrder], batchId + 1);
            log.info(`Placed order with id: ${orderIds.toString()}`);
            // Advance time (30min)
            log.info("Advance time 30min to make sure the new order expires");
            yield utilities_1.waitForNSeconds(1800, web3);
            // Delete the new order
            yield util_1.deleteOrders(orderIds, [user1Address], exchange);
            log.info(`Environment setup complete for BatchExchange with address ${exchange.address}`);
            callback();
        }
        catch (error) {
            callback(error);
        }
    });
};
