"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 });
exports.VaultExt = exports.VaultStatusExt = void 0;
const utils_1 = require("../utils");
var VaultStatusExt;
(function (VaultStatusExt) {
    VaultStatusExt[VaultStatusExt["Active"] = 0] = "Active";
    VaultStatusExt[VaultStatusExt["Inactive"] = 1] = "Inactive";
    VaultStatusExt[VaultStatusExt["Liquidated"] = 2] = "Liquidated";
})(VaultStatusExt = exports.VaultStatusExt || (exports.VaultStatusExt = {}));
class VaultExt {
    constructor(api, oracleAPI, systemAPI, assetRegistryAPI, loansAPI, backingCollateral, id, status, bannedUntil, toBeIssuedTokens, issuedTokens, toBeRedeemedTokens, toBeReplacedTokens, replaceCollateral, liquidatedCollateral, secureCollateralThreshold) {
        this.api = api;
        this.oracleAPI = oracleAPI;
        this.systemAPI = systemAPI;
        this.assetRegistryAPI = assetRegistryAPI;
        this.loansAPI = loansAPI;
        this.backingCollateral = backingCollateral;
        this.id = id;
        this.status = status;
        this.bannedUntil = bannedUntil;
        this.toBeIssuedTokens = toBeIssuedTokens;
        this.issuedTokens = issuedTokens;
        this.toBeRedeemedTokens = toBeRedeemedTokens;
        this.toBeReplacedTokens = toBeReplacedTokens;
        this.replaceCollateral = replaceCollateral;
        this.liquidatedCollateral = liquidatedCollateral;
        this.secureCollateralThreshold = secureCollateralThreshold;
    }
    getRedeemableTokens() {
        return this.issuedTokens.sub(this.toBeRedeemedTokens);
    }
    getIssuableTokens() {
        return __awaiter(this, void 0, void 0, function* () {
            const balance = yield this.api.rpc.vaultRegistry.getIssueableTokensFromVault({
                account_id: this.id.accountId,
                currencies: this.id.currencies,
            });
            const wrapped = yield utils_1.currencyIdToMonetaryCurrency(this.assetRegistryAPI, this.loansAPI, this.id.currencies.wrapped);
            return utils_1.newMonetaryAmount(balance.amount.toString(), wrapped);
        });
    }
    isBanned() {
        return __awaiter(this, void 0, void 0, function* () {
            const currentBlockNumber = yield this.systemAPI.getCurrentActiveBlockNumber();
            if (!this.bannedUntil) {
                return false;
            }
            return this.bannedUntil >= currentBlockNumber;
        });
    }
    getBackedTokens() {
        return this.issuedTokens.add(this.toBeIssuedTokens);
    }
    getFreeCollateral() {
        return __awaiter(this, void 0, void 0, function* () {
            const usedCollateral = yield this.getUsedCollateral();
            const totalCollateral = yield this.computeBackingCollateral();
            return totalCollateral.sub(usedCollateral);
        });
    }
    getUsedCollateral() {
        return __awaiter(this, void 0, void 0, function* () {
            const backedTokens = this.getBackedTokens();
            const backedTokensInCollateral = yield this.oracleAPI.convertWrappedToCurrency(
            // Force type-assert here as the oracle API only uses wrapped Bitcoin
            backedTokens, yield utils_1.currencyIdToMonetaryCurrency(this.assetRegistryAPI, this.loansAPI, this.id.currencies.collateral));
            const secureCollateralThreshold = this.getSecureCollateralThreshold();
            const usedCollateral = backedTokensInCollateral.mul(secureCollateralThreshold);
            const totalCollateral = yield this.computeBackingCollateral();
            return totalCollateral.min(usedCollateral);
        });
    }
    getSecureCollateralThreshold() {
        return this.secureCollateralThreshold;
    }
    // TODO: The functions below are duplicated from other APIs. Remove them after APIs
    // are refactored to the builder pattern
    computeBackingCollateral(nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce();
            }
            const rawBackingCollateral = yield this.api.query.vaultStaking.totalCurrentStake(nonce, this.id);
            const collateralCurrency = yield utils_1.currencyIdToMonetaryCurrency(this.assetRegistryAPI, this.loansAPI, this.id.currencies.collateral);
            return utils_1.newMonetaryAmount(utils_1.decodeFixedPointType(rawBackingCollateral), collateralCurrency);
        });
    }
    getStakingPoolNonce() {
        return __awaiter(this, void 0, void 0, function* () {
            const rawNonce = yield this.api.query.vaultStaking.nonce(this.id);
            return rawNonce.toNumber();
        });
    }
}
exports.VaultExt = VaultExt;
//# sourceMappingURL=vault.js.map