"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 api_1 = require("@polkadot/api");
const index_1 = require("../../../../../src/index");
const bitcoin_core_client_1 = require("../../../../../src/utils/bitcoin-core-client");
const factory_1 = require("../../../../../src/factory");
const config_1 = require("../../../../config");
const chai_1 = require("../../../../chai");
const issueRedeem_1 = require("../../../../../src/utils/issueRedeem");
const src_1 = require("../../../../../src");
describe("replace", () => {
    let api;
    let bitcoinCoreClient;
    let keyring;
    let userAccount;
    let vault_3;
    let vault_3_ids;
    let vault_2;
    let vault_2_ids;
    let interBtcAPI;
    let wrappedCurrency;
    before(function () {
        return __awaiter(this, void 0, void 0, function* () {
            api = yield factory_1.createSubstrateAPI(config_1.PARACHAIN_ENDPOINT);
            keyring = new api_1.Keyring({ type: "sr25519" });
            bitcoinCoreClient = new bitcoin_core_client_1.BitcoinCoreClient(config_1.BITCOIN_CORE_NETWORK, config_1.BITCOIN_CORE_HOST, config_1.BITCOIN_CORE_USERNAME, config_1.BITCOIN_CORE_PASSWORD, config_1.BITCOIN_CORE_PORT, config_1.BITCOIN_CORE_WALLET);
            userAccount = keyring.addFromUri(config_1.USER_1_URI);
            interBtcAPI = new index_1.DefaultInterBtcApi(api, "regtest", userAccount, config_1.ESPLORA_BASE_PATH);
            wrappedCurrency = interBtcAPI.getWrappedCurrency();
            const collateralCurrencies = index_1.getCorrespondingCollateralCurrencies(interBtcAPI.getGovernanceCurrency());
            vault_3 = keyring.addFromUri(config_1.VAULT_3_URI);
            vault_3_ids = collateralCurrencies
                .map(collateralCurrency => src_1.newVaultId(api, vault_3.address, collateralCurrency, wrappedCurrency));
            vault_2 = keyring.addFromUri(config_1.VAULT_2_URI);
            vault_2_ids = collateralCurrencies
                .map(collateralCurrency => src_1.newVaultId(api, vault_2.address, collateralCurrency, wrappedCurrency));
        });
    });
    after(() => __awaiter(void 0, void 0, void 0, function* () {
        api.disconnect();
    }));
    describe("request", () => {
        let dustValue;
        let feesEstimate;
        before(() => __awaiter(void 0, void 0, void 0, function* () {
            dustValue = yield interBtcAPI.replace.getDustValue();
            feesEstimate = index_1.newMonetaryAmount((yield interBtcAPI.oracle.getBitcoinFees()), wrappedCurrency, false);
        }));
        it("should request vault replacement", () => __awaiter(void 0, void 0, void 0, function* () {
            for (const vault_3_id of vault_3_ids) {
                // try to set value above dust + estimated fees
                const issueAmount = dustValue.add(feesEstimate).mul(1.2);
                const replaceAmount = dustValue;
                yield issueRedeem_1.issueSingle(interBtcAPI, bitcoinCoreClient, userAccount, issueAmount, vault_3_id);
                interBtcAPI.setAccount(vault_3);
                yield interBtcAPI.replace.request(replaceAmount, src_1.currencyIdToMonetaryCurrency(vault_3_id.currencies.collateral));
                const finalizedPromise = new Promise((resolve, _) => interBtcAPI.system.subscribeToFinalizedBlockHeads((header) => __awaiter(void 0, void 0, void 0, function* () {
                    const events = yield interBtcAPI.api.query.system.events.at(header.parentHash);
                    if (index_1.DefaultTransactionAPI.doesArrayContainEvent(events, api.events.replace.AcceptReplace)) {
                        resolve();
                    }
                })));
                yield finalizedPromise;
            }
            const requestsList = yield interBtcAPI.replace.list();
            const requestsMap = yield interBtcAPI.replace.map();
            chai_1.assert.equal(requestsList.length, vault_3_ids.length, `Expected ${vault_3_ids.length} requests in list, got ${requestsList.length}`);
            chai_1.assert.equal(requestsMap.size, vault_3_ids.length, `Expected ${vault_3_ids.length} requests in map, got ${requestsMap.size}`);
            // Need to manually compare some fields
            const membersFromListToExpect = requestsList.map(req => ({
                btcAddress: req.btcAddress,
                btcHeight: req.btcHeight,
                amount: req.amount.toString()
            }));
            const membersFromMapToCheck = Array.from(requestsMap.values()).map(req => ({
                btcAddress: req.btcAddress,
                btcHeight: req.btcHeight,
                amount: req.amount.toString()
            }));
            chai_1.expect(membersFromMapToCheck).to.deep.include.members(membersFromListToExpect);
        })).timeout(2000000);
        it("should fail vault replace request if not having enough tokens", () => __awaiter(void 0, void 0, void 0, function* () {
            for (const vault_2_id of vault_2_ids) {
                const currencyTicker = src_1.currencyIdToMonetaryCurrency(vault_2_id.currencies.collateral).ticker;
                interBtcAPI.setAccount(vault_2);
                // fetch tokens held by vault
                const tokensInVault = yield interBtcAPI.vaults.getIssuedAmount(src_1.newAccountId(api, vault_2.address), index_1.currencyIdToLiteral(vault_2_id.currencies.collateral));
                // make sure vault does not hold enough issued tokens to request a replace
                const replaceAmount = dustValue.add(tokensInVault);
                try {
                    yield interBtcAPI.replace.request(replaceAmount, src_1.currencyIdToMonetaryCurrency(vault_2_id.currencies.collateral));
                    chai_1.assert.fail(`Expected error to be thrown due to lack of issued tokens
                        for vault (collateral: ${currencyTicker}), but call completed.`);
                }
                catch (e) {
                    chai_1.assert.isTrue(e instanceof Error, `Expected replace request to fail with Error (${currencyTicker} vault)`);
                }
            }
        })).timeout(600000);
    });
    it("should getDustValue", () => __awaiter(void 0, void 0, void 0, function* () {
        const dustValue = yield interBtcAPI.replace.getDustValue();
        chai_1.assert.equal(dustValue.str.BTC(), "0.00001");
    })).timeout(500);
    it("should getReplacePeriod", () => __awaiter(void 0, void 0, void 0, function* () {
        const replacePeriod = yield interBtcAPI.replace.getReplacePeriod();
        chai_1.assert.equal(replacePeriod.toString(), "7200");
    })).timeout(500);
    it("should list replace request by a vault", () => __awaiter(void 0, void 0, void 0, function* () {
        const vault3Id = src_1.newAccountId(api, vault_3.address);
        const replaceRequests = yield interBtcAPI.replace.mapReplaceRequests(vault3Id);
        replaceRequests.forEach((request) => {
            chai_1.assert.deepEqual(request.oldVault.accountId, vault3Id);
        });
    }));
});
//# sourceMappingURL=replace.test.js.map