"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());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const api_1 = require("@polkadot/api");
const bn_js_1 = __importDefault(require("bn.js"));
const index_1 = require("../../../../../src/index");
const src_1 = require("../../../../../src");
const utils_1 = require("../../../../../src/utils");
const factory_1 = require("../../../../../src/factory");
const chai_1 = require("../../../../chai");
const config_1 = require("../../../../config");
const helpers_1 = require("../../../../utils/helpers");
// TODO: readd this once we want to activate nomination
describe.skip("NominationAPI", () => {
    let api;
    let userInterBtcAPI;
    let sudoInterBtcAPI;
    let assetRegistry;
    let sudoAccount;
    let userAccount;
    let vault_1;
    let vault_1_ids;
    let bitcoinCoreClient;
    let wrappedCurrency;
    let collateralCurrencies;
    before(() => __awaiter(void 0, void 0, void 0, function* () {
        api = yield factory_1.createSubstrateAPI(config_1.PARACHAIN_ENDPOINT);
        const keyring = new api_1.Keyring({ type: "sr25519" });
        sudoAccount = keyring.addFromUri(config_1.SUDO_URI);
        userAccount = keyring.addFromUri(config_1.USER_1_URI);
        // TODO: remove all uses of config currencies and query the chain instead
        userInterBtcAPI = new index_1.DefaultInterBtcApi(api, "regtest", userAccount, config_1.ESPLORA_BASE_PATH);
        sudoInterBtcAPI = new index_1.DefaultInterBtcApi(api, "regtest", sudoAccount, config_1.ESPLORA_BASE_PATH);
        assetRegistry = new index_1.DefaultAssetRegistryAPI(api);
        collateralCurrencies = utils_1.getCorrespondingCollateralCurrencies(userInterBtcAPI.getGovernanceCurrency());
        wrappedCurrency = userInterBtcAPI.getWrappedCurrency();
        vault_1 = keyring.addFromUri(config_1.VAULT_1_URI);
        vault_1_ids = collateralCurrencies.map((collateralCurrency) => src_1.newVaultId(api, vault_1.address, collateralCurrency, wrappedCurrency));
        if (!(yield sudoInterBtcAPI.nomination.isNominationEnabled())) {
            console.log("Enabling nomination...");
            yield helpers_1.sudo(sudoInterBtcAPI, () => sudoInterBtcAPI.nomination.setNominationEnabled(true));
        }
        // The account of a vault from docker-compose
        vault_1 = keyring.addFromUri(config_1.VAULT_1_URI);
        bitcoinCoreClient = new src_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);
    }));
    after(() => {
        return api.disconnect();
    });
    it("Should opt a vault in and out of nomination", () => __awaiter(void 0, void 0, void 0, function* () {
        for (const vault_1_id of vault_1_ids) {
            yield optInWithAccount(vault_1, yield src_1.currencyIdToMonetaryCurrency(assetRegistry, vault_1_id.currencies.collateral));
            const nominationVaults = yield userInterBtcAPI.nomination.listVaults();
            chai_1.assert.equal(1, nominationVaults.length);
            chai_1.assert.equal(vault_1.address, nominationVaults.map((v) => v.accountId.toString())[0]);
            yield optOutWithAccount(vault_1, yield src_1.currencyIdToMonetaryCurrency(assetRegistry, vault_1_id.currencies.collateral));
            chai_1.assert.equal(0, (yield userInterBtcAPI.nomination.listVaults()).length);
        }
    })).timeout(2 * 60000);
    function setIssueFee(x) {
        return __awaiter(this, void 0, void 0, function* () {
            yield utils_1.setNumericStorage(api, "Fee", "IssueFee", x, sudoAccount, 128);
        });
    }
    it("Should nominate to and withdraw from a vault", () => __awaiter(void 0, void 0, void 0, function* () {
        for (const vault_1_id of vault_1_ids) {
            yield optInWithAccount(vault_1, yield src_1.currencyIdToMonetaryCurrency(assetRegistry, vault_1_id.currencies.collateral));
            const issueFee = yield userInterBtcAPI.fee.getIssueFee();
            const collateralCurrency = yield src_1.currencyIdToMonetaryCurrency(assetRegistry, vault_1_id.currencies.collateral);
            const nominatorDeposit = utils_1.newMonetaryAmount(1, collateralCurrency, true);
            try {
                // Set issue fees to 100%
                yield setIssueFee(new bn_js_1.default("1000000000000000000"));
                const stakingCapacityBeforeNomination = yield userInterBtcAPI.vaults.getStakingCapacity(vault_1_id.accountId, collateralCurrency);
                // Deposit
                yield userInterBtcAPI.nomination.depositCollateral(vault_1_id.accountId, nominatorDeposit);
                const stakingCapacityAfterNomination = yield userInterBtcAPI.vaults.getStakingCapacity(vault_1_id.accountId, collateralCurrency);
                chai_1.assert.equal(stakingCapacityBeforeNomination.sub(nominatorDeposit).toString(), stakingCapacityAfterNomination.toString(), "Nomination failed to decrease staking capacity");
                const nominationPairs = yield userInterBtcAPI.nomination.list();
                chai_1.assert.equal(2, nominationPairs.length, "There should be one nomination pair in the system, besides the vault to itself");
                const userAddress = userAccount.address;
                const vault_1Address = vault_1.address;
                const nomination = nominationPairs.find((nomination) => userAddress == nomination.nominatorId.toString());
                chai_1.assert.equal(userAddress, nomination.nominatorId.toString());
                chai_1.assert.equal(vault_1Address, nomination.vaultId.accountId.toString());
                const amountToIssue = utils_1.newMonetaryAmount(0.00001, wrappedCurrency, true);
                yield utils_1.issueSingle(userInterBtcAPI, bitcoinCoreClient, userAccount, amountToIssue, vault_1_id);
                const wrappedRewardsBeforeWithdrawal = (yield userInterBtcAPI.nomination.getNominatorReward(vault_1_id.accountId, collateralCurrency, wrappedCurrency, src_1.newAccountId(api, userAccount.address))).toBig();
                chai_1.assert.isTrue(wrappedRewardsBeforeWithdrawal.gt(0), "Nominator should receive non-zero wrapped tokens");
                // Withdraw Rewards
                yield userInterBtcAPI.rewards.withdrawRewards(vault_1_id);
                // Withdraw Collateral
                yield userInterBtcAPI.nomination.withdrawCollateral(vault_1_id.accountId, nominatorDeposit);
                const nominatorsAfterWithdrawal = yield userInterBtcAPI.nomination.list();
                // The vault always has a "nomination" to itself
                chai_1.assert.equal(1, nominatorsAfterWithdrawal.length);
                const totalNomination = yield userInterBtcAPI.nomination.getTotalNomination(src_1.newAccountId(api, userAccount.address), yield src_1.currencyIdToMonetaryCurrency(assetRegistry, vault_1_id.currencies.collateral));
                chai_1.assert.equal(totalNomination.toString(), "0");
            }
            finally {
                yield setIssueFee(src_1.encodeUnsignedFixedPoint(api, issueFee));
                yield optOutWithAccount(vault_1, yield src_1.currencyIdToMonetaryCurrency(assetRegistry, vault_1_id.currencies.collateral));
            }
        }
    })).timeout(10 * 60000);
    function optInWithAccount(vaultAccount, collateralCurrency) {
        return __awaiter(this, void 0, void 0, function* () {
            // will fail if vault is already opted in
            yield helpers_1.callWith(userInterBtcAPI, vaultAccount, () => userInterBtcAPI.nomination.optIn(collateralCurrency));
        });
    }
    function optOutWithAccount(vaultAccount, collateralCurrency) {
        return __awaiter(this, void 0, void 0, function* () {
            yield helpers_1.callWith(userInterBtcAPI, vaultAccount, () => userInterBtcAPI.nomination.optOut(collateralCurrency));
        });
    }
});
//# sourceMappingURL=nomination.test.js.map