"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.DefaultRewardsAPI = void 0;
const utils_1 = require("../utils");
class DefaultRewardsAPI {
    constructor(api, wrappedCurrency, transactionAPI, assetRegistry, loansAPI) {
        this.api = api;
        this.wrappedCurrency = wrappedCurrency;
        this.transactionAPI = transactionAPI;
        this.assetRegistry = assetRegistry;
        this.loansAPI = loansAPI;
    }
    withdrawRewards(vaultId, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            const definedNonce = nonce
                ? nonce
                : yield this.getStakingPoolNonce(yield utils_1.currencyIdToMonetaryCurrency(this.assetRegistry, this.loansAPI, vaultId.currencies.collateral), vaultId.accountId);
            const tx = this.api.tx.fee.withdrawRewards(vaultId, definedNonce.toString());
            yield this.transactionAPI.sendLogged(tx, this.api.events.vaultStaking.WithdrawReward, true);
        });
    }
    computeRewardInStakingPool(vaultAccountId, nominatorId, collateralCurrency, rewardCurrency, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            rewardCurrency = rewardCurrency || this.wrappedCurrency;
            const [stake, rewardPerToken, rewardTally] = yield Promise.all([
                this.getStakingPoolStake(collateralCurrency, vaultAccountId, nominatorId, nonce),
                this.getStakingPoolRewardPerToken(rewardCurrency, vaultAccountId, collateralCurrency, nonce),
                this.getStakingPoolRewardTally(rewardCurrency, vaultAccountId, nominatorId, collateralCurrency, nonce),
            ]);
            const rawLazyDistribution = utils_1.computeLazyDistribution(stake, rewardPerToken, rewardTally);
            return utils_1.newMonetaryAmount(rawLazyDistribution, rewardCurrency);
        });
    }
    getStakingPoolNonce(collateralCurrency, vaultAccountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            const rawNonce = yield this.api.query.vaultStaking.nonce(vaultId);
            return rawNonce.toNumber();
        });
    }
    getStakingPoolStake(collateralCurrency, vaultAccountId, nominatorId, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(collateralCurrency, vaultAccountId);
            }
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            const rawStake = yield this.api.query.vaultStaking.stake(nonce, [vaultId, nominatorId]);
            return utils_1.decodeFixedPointType(rawStake);
        });
    }
    getStakingPoolTotalStake(collateralCurrency, vaultAccountId, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(collateralCurrency, vaultAccountId);
            }
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            const rawTotalStake = yield this.api.query.vaultStaking.totalCurrentStake(nonce, vaultId);
            return utils_1.decodeFixedPointType(rawTotalStake);
        });
    }
    getStakingPoolRewardTally(rewardCurrency, vaultAccountId, nominatorId, collateralCurrency, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(collateralCurrency, vaultAccountId);
            }
            const rewardCurrencyPrimitive = utils_1.newCurrencyId(this.api, rewardCurrency);
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            return utils_1.decodeFixedPointType(yield this.api.query.vaultStaking.rewardTally(rewardCurrencyPrimitive, [nonce, vaultId, nominatorId]));
        });
    }
    getStakingPoolRewardPerToken(wrappedCurrency, vaultAccountId, collateralCurrency, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(collateralCurrency, vaultAccountId);
            }
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            const wrappedCurrencyId = utils_1.newCurrencyId(this.api, wrappedCurrency);
            return utils_1.decodeFixedPointType(yield this.api.query.vaultStaking.rewardPerToken(wrappedCurrencyId, [nonce, vaultId]));
        });
    }
    computeCollateralInStakingPool(vaultId, nominatorId) {
        return __awaiter(this, void 0, void 0, function* () {
            const collateralCurrency = yield utils_1.currencyIdToMonetaryCurrency(this.assetRegistry, this.loansAPI, vaultId.currencies.collateral);
            const [stake, slashPerToken, slashTally] = yield Promise.all([
                this.getStakingPoolStake(collateralCurrency, vaultId.accountId, nominatorId),
                this.getStakingPoolSlashPerToken(collateralCurrency, vaultId.accountId),
                this.getStakingPoolSlashTally(collateralCurrency, vaultId.accountId, nominatorId),
            ]);
            const toSlash = utils_1.computeLazyDistribution(stake, slashPerToken, slashTally);
            return utils_1.newMonetaryAmount(stake.sub(toSlash), yield utils_1.currencyIdToMonetaryCurrency(this.assetRegistry, this.loansAPI, vaultId.currencies.collateral));
        });
    }
    getStakingPoolSlashPerToken(vaultCollateral, vaultAccountId, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(vaultCollateral, vaultAccountId);
            }
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), vaultCollateral, this.wrappedCurrency);
            return utils_1.decodeFixedPointType(yield this.api.query.vaultStaking.slashPerToken(nonce, vaultId));
        });
    }
    getStakingPoolSlashTally(collateralCurrency, vaultAccountId, nominatorId, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(collateralCurrency, vaultAccountId);
            }
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            return utils_1.decodeFixedPointType(yield this.api.query.vaultStaking.slashTally(nonce, [vaultId, nominatorId]));
        });
    }
    computeRewardInRewardsPool(rewardCurrency, vaultCollateral, vaultAccountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const vaultCurrencyPair = utils_1.newVaultCurrencyPair(this.api, vaultCollateral, this.wrappedCurrency);
            const params = {
                account_id: vaultAccountId,
                currencies: vaultCurrencyPair,
            };
            const reward = yield this.api.rpc.reward.computeVaultReward(params, utils_1.newCurrencyId(this.api, rewardCurrency));
            return utils_1.newMonetaryAmount(reward.amount.toString(), rewardCurrency);
        });
    }
    getRewardsPoolStake(vaultCollateral, vaultAccountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const collateralCurrencyId = utils_1.newCurrencyId(this.api, vaultCollateral);
            const collateralCurrency = yield utils_1.currencyIdToMonetaryCurrency(this.assetRegistry, this.loansAPI, collateralCurrencyId);
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            return utils_1.decodeFixedPointType(yield this.api.query.vaultRewards.stake([collateralCurrencyId, vaultId]));
        });
    }
    getRewardsPoolRewardTally(rewardCurrency, vaultCollateral, vaultAccountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const rewardCurrencyId = utils_1.newCurrencyId(this.api, rewardCurrency);
            const collateralCurrencyId = utils_1.newCurrencyId(this.api, vaultCollateral);
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), vaultCollateral, this.wrappedCurrency);
            return utils_1.decodeFixedPointType(yield this.api.query.vaultRewards.rewardTally(rewardCurrencyId, [collateralCurrencyId, vaultId]));
        });
    }
    getRewardsPoolRewardPerToken(rewardCurrency, collateralCurrency) {
        return __awaiter(this, void 0, void 0, function* () {
            const rewardCurrencyId = utils_1.newCurrencyId(this.api, rewardCurrency);
            const collateralCurrencyId = utils_1.newCurrencyId(this.api, collateralCurrency);
            return utils_1.decodeFixedPointType(yield this.api.query.vaultRewards.rewardPerToken(rewardCurrencyId, collateralCurrencyId));
        });
    }
    getRewardPerBlock(governanceCurrency) {
        return __awaiter(this, void 0, void 0, function* () {
            const rawRewardPerBlock = yield this.api.query.vaultAnnuity.rewardPerBlock();
            return utils_1.newMonetaryAmount(rawRewardPerBlock.toString(), governanceCurrency);
        });
    }
}
exports.DefaultRewardsAPI = DefaultRewardsAPI;
//# sourceMappingURL=rewards.js.map