"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 });
exports.tokenSymbolToCurrency = exports.currencyIdToMonetaryCurrency = exports.isCurrencyEqual = exports.isCurrency = exports.isForeignAsset = exports.getCollateralCurrencies = exports.toVoting = exports.createExchangeRateOracleKey = exports.createInclusionOracleKey = exports.newCollateralBTCExchangeRate = exports.newMonetaryAmount = exports.atomicToBaseAmount = exports.roundLastNDigits = exports.computeLazyDistribution = exports.satToMBTC = exports.roundTwoDecimals = exports.ATOMIC_UNIT = exports.MBTC_IN_SAT = void 0;
const big_js_1 = __importDefault(require("big.js"));
const bn_js_1 = __importDefault(require("bn.js"));
const monetary_js_1 = require("@interlay/monetary-js");
const encoding_1 = require("./encoding");
// set maximum exponents
big_js_1.default.PE = 21;
big_js_1.default.NE = -12;
exports.MBTC_IN_SAT = 100000;
exports.ATOMIC_UNIT = 0;
function roundTwoDecimals(input) {
    const number = new big_js_1.default(input);
    return number.round(2).toString();
}
exports.roundTwoDecimals = roundTwoDecimals;
function satToMBTC(sat) {
    const satAmount = new big_js_1.default(sat);
    return satAmount.div(exports.MBTC_IN_SAT).toString();
}
exports.satToMBTC = satToMBTC;
function computeLazyDistribution(stake, perToken, tally) {
    return stake.mul(perToken).sub(tally);
}
exports.computeLazyDistribution = computeLazyDistribution;
function roundLastNDigits(n, x) {
    const power = Math.pow(10, n);
    // Use BN such that we perform integer division
    const bigNumber = new bn_js_1.default(x.toString());
    return bigNumber.div(new bn_js_1.default(power)).mul(new bn_js_1.default(power)).toString();
}
exports.roundLastNDigits = roundLastNDigits;
function atomicToBaseAmount(atomicAmount, currency) {
    return new big_js_1.default(atomicAmount).div(new big_js_1.default(10).pow(currency.decimals));
}
exports.atomicToBaseAmount = atomicToBaseAmount;
function newMonetaryAmount(amount, currency, base = false) {
    const finalAmount = base ? new big_js_1.default(amount) : atomicToBaseAmount(amount, currency);
    return new monetary_js_1.MonetaryAmount(currency, finalAmount);
}
exports.newMonetaryAmount = newMonetaryAmount;
function newCollateralBTCExchangeRate(rate, counterCurrency, useBaseUnits = false) {
    const [baseCurrencyUnit, counterCurrencyUnit] = useBaseUnits
        ? [monetary_js_1.Bitcoin.decimals, counterCurrency.decimals]
        : [exports.ATOMIC_UNIT, exports.ATOMIC_UNIT];
    return new monetary_js_1.ExchangeRate(monetary_js_1.Bitcoin, counterCurrency, rate, baseCurrencyUnit, counterCurrencyUnit);
}
exports.newCollateralBTCExchangeRate = newCollateralBTCExchangeRate;
function createInclusionOracleKey(api, type) {
    return api.createType("InterbtcPrimitivesOracleKey", { FeeEstimation: type });
}
exports.createInclusionOracleKey = createInclusionOracleKey;
function createExchangeRateOracleKey(api, collateralCurrency) {
    const currencyId = encoding_1.newCurrencyId(api, collateralCurrency);
    return api.createType("InterbtcPrimitivesOracleKey", { ExchangeRate: currencyId });
}
exports.createExchangeRateOracleKey = createExchangeRateOracleKey;
function toVoting(governanceCurrency) {
    switch (governanceCurrency) {
        case monetary_js_1.Interlay:
            return monetary_js_1.VoteInterlay;
        case monetary_js_1.Kintsugi:
            return monetary_js_1.VoteKintsugi;
        default:
            throw new Error("Provided currency is not a governance currency");
    }
}
exports.toVoting = toVoting;
/**
 * Get all collateral currencies (tokens as well as foreign assets).
 *
 * Will return all collateral currencies for which the parachain has a system collateral ceiling value
 * greater than zero.
 * @param api ApiPromise instance to query the parachain
 * @param assetRegistry AssetRegistryAPI instance to fetch foreign asset data (if needed)
 * @returns An array of collateral currencies.
 */
function getCollateralCurrencies(api, assetRegistry) {
    return __awaiter(this, void 0, void 0, function* () {
        const collatCeilEntries = yield api.query.vaultRegistry.systemCollateralCeiling.entries();
        const isOptionGreaterThanZero = (value) => value.isNone ? false : value.unwrap().toBn().gt(new bn_js_1.default(0));
        const collateralCurrencyPrimitives = collatCeilEntries
            .filter(([_, ceiling]) => isOptionGreaterThanZero(ceiling))
            .map(([storageKey, _]) => encoding_1.storageKeyToNthInner(storageKey));
        return Promise.all(collateralCurrencyPrimitives.map((currencyPair) => currencyIdToMonetaryCurrency(assetRegistry, currencyPair.collateral)));
    });
}
exports.getCollateralCurrencies = getCollateralCurrencies;
function isForeignAsset(currencyExt) {
    // disable rule, use of any is deliberate for run time check
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    return currencyExt.id !== undefined;
}
exports.isForeignAsset = isForeignAsset;
function isCurrency(currencyExt) {
    return !isForeignAsset(currencyExt);
}
exports.isCurrency = isCurrency;
function isCurrencyEqual(currency, otherCurrency) {
    if (isForeignAsset(currency) && isForeignAsset(otherCurrency)) {
        return currency.id === otherCurrency.id;
    }
    else if (isCurrency(currency) && isCurrency(otherCurrency)) {
        return currency.ticker === otherCurrency.ticker;
    }
    return false;
}
exports.isCurrencyEqual = isCurrencyEqual;
function currencyIdToMonetaryCurrency(assetRegistryApi, currencyId) {
    return __awaiter(this, void 0, void 0, function* () {
        if (currencyId.isToken) {
            return tokenSymbolToCurrency(currencyId.asToken);
        }
        else if (currencyId.isForeignAsset) {
            const foreignAssetId = currencyId.asForeignAsset;
            return assetRegistryApi.getForeignAsset(foreignAssetId);
        }
        throw new Error(`No handling implemented for currencyId type of ${currencyId.type}`);
    });
}
exports.currencyIdToMonetaryCurrency = currencyIdToMonetaryCurrency;
/**
 * A method that will only try to find a hard-coded currencies.
 * Only for use when we are certain the currency is not a foreign asset.
 * @param tokenSymbol the InterbtcPrimitivesTokenSymbol to look up
 */
function tokenSymbolToCurrency(tokenSymbol) {
    if (tokenSymbol.isIbtc) {
        return monetary_js_1.InterBtc;
    }
    else if (tokenSymbol.isDot) {
        return monetary_js_1.Polkadot;
    }
    else if (tokenSymbol.isKsm) {
        return monetary_js_1.Kusama;
    }
    else if (tokenSymbol.isKbtc) {
        return monetary_js_1.KBtc;
    }
    else if (tokenSymbol.isKint) {
        return monetary_js_1.Kintsugi;
    }
    else if (tokenSymbol.isIntr) {
        return monetary_js_1.Interlay;
    }
    throw new Error(`No entry provided for token symbol of type '${tokenSymbol === null || tokenSymbol === void 0 ? void 0 : tokenSymbol.type}'`);
}
exports.tokenSymbolToCurrency = tokenSymbolToCurrency;
//# sourceMappingURL=currency.js.map