"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");
const types_1 = require("../types");
class DefaultRewardsAPI {
    constructor(api, wrappedCurrency, transactionAPI) {
        this.api = api;
        this.wrappedCurrency = wrappedCurrency;
        this.transactionAPI = transactionAPI;
    }
    withdrawRewards(vaultId, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            const definedNonce = nonce
                ? nonce
                : yield this.getStakingPoolNonce(types_1.currencyIdToLiteral(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, collateralCurrencyId, rewardCurrencyId, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            const wrappedCurrencyId = types_1.tickerToCurrencyIdLiteral(this.wrappedCurrency.ticker);
            rewardCurrencyId = (rewardCurrencyId ? rewardCurrencyId : wrappedCurrencyId);
            const [stake, rewardPerToken, rewardTally] = yield Promise.all([
                this.getStakingPoolStake(collateralCurrencyId, vaultAccountId, nominatorId, nonce),
                this.getStakingPoolRewardPerToken(rewardCurrencyId, vaultAccountId, collateralCurrencyId, nonce),
                this.getStakingPoolRewardTally(rewardCurrencyId, vaultAccountId, nominatorId, collateralCurrencyId, nonce),
            ]);
            const rawLazyDistribution = utils_1.computeLazyDistribution(stake, rewardPerToken, rewardTally);
            return utils_1.newMonetaryAmount(rawLazyDistribution, types_1.currencyIdLiteralToMonetaryCurrency(this.api, rewardCurrencyId));
        });
    }
    getStakingPoolNonce(collateralCurrencyIdLiteral, vaultAccountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const collateralCurrency = types_1.currencyIdToMonetaryCurrency(utils_1.newCurrencyId(this.api, collateralCurrencyIdLiteral));
            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(collateralCurrencyIdLiteral, vaultAccountId, nominatorId, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(collateralCurrencyIdLiteral, vaultAccountId);
            }
            const collateralCurrency = types_1.currencyIdToMonetaryCurrency(utils_1.newCurrencyId(this.api, collateralCurrencyIdLiteral));
            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(collateralCurrencyIdLiteral, vaultAccountId, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(collateralCurrencyIdLiteral, vaultAccountId);
            }
            const collateralCurrency = types_1.currencyIdToMonetaryCurrency(utils_1.newCurrencyId(this.api, collateralCurrencyIdLiteral));
            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(rewardCurrencyIdLiteral, vaultAccountId, nominatorId, collateralCurrencyIdLiteral, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(collateralCurrencyIdLiteral, vaultAccountId);
            }
            const collateralCurrency = types_1.currencyIdLiteralToMonetaryCurrency(this.api, collateralCurrencyIdLiteral);
            const rewardCurrency = utils_1.newCurrencyId(this.api, rewardCurrencyIdLiteral);
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            return utils_1.decodeFixedPointType(yield this.api.query.vaultStaking.rewardTally(rewardCurrency, [nonce, vaultId, nominatorId]));
        });
    }
    getStakingPoolRewardPerToken(wrappedCurrencyIdLiteral, vaultAccountId, collateralCurrencyIdLiteral, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(collateralCurrencyIdLiteral, vaultAccountId);
            }
            const collateralCurrency = types_1.currencyIdToMonetaryCurrency(utils_1.newCurrencyId(this.api, collateralCurrencyIdLiteral));
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            const wrappedCurrencyId = utils_1.newCurrencyId(this.api, wrappedCurrencyIdLiteral);
            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 collateralCurrencyIdLiteral = types_1.currencyIdToLiteral(vaultId.currencies.collateral);
            const [stake, slashPerToken, slashTally] = yield Promise.all([
                this.getStakingPoolStake(collateralCurrencyIdLiteral, vaultId.accountId, nominatorId),
                this.getStakingPoolSlashPerToken(collateralCurrencyIdLiteral, vaultId.accountId),
                this.getStakingPoolSlashTally(collateralCurrencyIdLiteral, vaultId.accountId, nominatorId),
            ]);
            const toSlash = utils_1.computeLazyDistribution(stake, slashPerToken, slashTally);
            return utils_1.newMonetaryAmount(stake.sub(toSlash), types_1.currencyIdToMonetaryCurrency(vaultId.currencies.collateral));
        });
    }
    getStakingPoolSlashPerToken(vaultCollateralIdLiteral, vaultAccountId, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(vaultCollateralIdLiteral, vaultAccountId);
            }
            const collateralCurrency = types_1.currencyIdToMonetaryCurrency(utils_1.newCurrencyId(this.api, vaultCollateralIdLiteral));
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            return utils_1.decodeFixedPointType(yield this.api.query.vaultStaking.slashPerToken(nonce, vaultId));
        });
    }
    getStakingPoolSlashTally(collateralCurrencyIdLiteral, vaultAccountId, nominatorId, nonce) {
        return __awaiter(this, void 0, void 0, function* () {
            if (nonce === undefined) {
                nonce = yield this.getStakingPoolNonce(collateralCurrencyIdLiteral, vaultAccountId);
            }
            const collateralCurrency = types_1.currencyIdToMonetaryCurrency(utils_1.newCurrencyId(this.api, collateralCurrencyIdLiteral));
            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(rewardCurrencyIdLiteral, vaultCollateralIdLiteral, vaultAccountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const stake = yield this.getRewardsPoolStake(vaultCollateralIdLiteral, vaultAccountId);
            const rewardPerToken = yield this.getRewardsPoolRewardPerToken(rewardCurrencyIdLiteral);
            const rewardTally = yield this.getRewardsPoolRewardTally(rewardCurrencyIdLiteral, vaultCollateralIdLiteral, vaultAccountId);
            const rawLazyDistribution = utils_1.computeLazyDistribution(stake, rewardPerToken, rewardTally);
            return utils_1.newMonetaryAmount(rawLazyDistribution, types_1.currencyIdLiteralToMonetaryCurrency(this.api, rewardCurrencyIdLiteral));
        });
    }
    getRewardsPoolStake(vaultCollateralIdLiteral, vaultAccountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const collateralCurrency = types_1.currencyIdToMonetaryCurrency(utils_1.newCurrencyId(this.api, vaultCollateralIdLiteral));
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            return utils_1.decodeFixedPointType(yield this.api.query.vaultRewards.stake(vaultId));
        });
    }
    getRewardsPoolRewardTally(rewardCurrencyIdLiteral, vaultCollateralIdLiteral, vaultAccountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const rewardCurrencyId = utils_1.newCurrencyId(this.api, rewardCurrencyIdLiteral);
            types_1.currencyIdToMonetaryCurrency(utils_1.newCurrencyId(this.api, rewardCurrencyIdLiteral));
            const collateralCurrency = types_1.currencyIdToMonetaryCurrency(utils_1.newCurrencyId(this.api, vaultCollateralIdLiteral));
            const vaultId = utils_1.newVaultId(this.api, vaultAccountId.toString(), collateralCurrency, this.wrappedCurrency);
            return utils_1.decodeFixedPointType(yield this.api.query.vaultRewards.rewardTally(rewardCurrencyId, vaultId));
        });
    }
    getRewardsPoolRewardPerToken(currencyId) {
        return __awaiter(this, void 0, void 0, function* () {
            return utils_1.decodeFixedPointType(yield this.api.query.vaultRewards.rewardPerToken(utils_1.newCurrencyId(this.api, currencyId)));
        });
    }
    getRewardPerBlock(governanceCurrency) {
        return __awaiter(this, void 0, void 0, function* () {
            const rawRewardPerBlock = yield this.api.query.vaultAnnuity.rewardPerBlock();
            return utils_1.newMonetaryAmount(rawRewardPerBlock.toString(), types_1.currencyIdLiteralToMonetaryCurrency(this.api, governanceCurrency));
        });
    }
}
exports.DefaultRewardsAPI = DefaultRewardsAPI;
//# sourceMappingURL=rewards.js.map