"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.DefaultEscrowAPI = void 0;
const utils_1 = require("../utils");
const types_1 = require("../types");
class DefaultEscrowAPI {
    constructor(api, governanceCurrency, systemAPI, transactionAPI) {
        this.api = api;
        this.governanceCurrency = governanceCurrency;
        this.systemAPI = systemAPI;
        this.transactionAPI = transactionAPI;
    }
    buildCreateLockExtrinsic(amount, unlockHeight) {
        return this.api.tx.escrow.createLock(amount.toString(true), unlockHeight);
    }
    createLock(amount, unlockHeight) {
        return __awaiter(this, void 0, void 0, function* () {
            const tx = this.buildCreateLockExtrinsic(amount, unlockHeight);
            yield this.transactionAPI.sendLogged(tx, this.api.events.escrow.Deposit, true);
        });
    }
    buildWithdrawExtrinsic() {
        return this.api.tx.escrow.withdraw();
    }
    withdraw() {
        return __awaiter(this, void 0, void 0, function* () {
            const tx = this.buildWithdrawExtrinsic();
            yield this.transactionAPI.sendLogged(tx, this.api.events.escrow.Withdraw, true);
        });
    }
    buildWithdrawRewardsExtrinsic() {
        return this.api.tx.escrowAnnuity.withdrawRewards();
    }
    withdrawRewards() {
        return __awaiter(this, void 0, void 0, function* () {
            const tx = this.buildWithdrawRewardsExtrinsic();
            yield this.transactionAPI.sendLogged(tx, this.api.events.escrowRewards.WithdrawReward, true);
        });
    }
    buildIncreaseAmountExtrinsic(amount) {
        return this.api.tx.escrow.increaseAmount(amount.toString(true));
    }
    increaseAmount(amount) {
        return __awaiter(this, void 0, void 0, function* () {
            const tx = this.buildIncreaseAmountExtrinsic(amount);
            yield this.transactionAPI.sendLogged(tx, this.api.events.escrow.Deposit, true);
        });
    }
    buildIncreaseUnlockHeightExtrinsic(unlockHeight) {
        return this.api.tx.escrow.increaseUnlockHeight(unlockHeight);
    }
    increaseUnlockHeight(unlockHeight) {
        return __awaiter(this, void 0, void 0, function* () {
            const tx = this.buildIncreaseUnlockHeightExtrinsic(unlockHeight);
            yield this.transactionAPI.sendLogged(tx, this.api.events.escrow.Deposit, true);
        });
    }
    getRewards(accountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const reward = yield this.api.rpc.reward.computeEscrowReward(accountId, utils_1.newCurrencyId(this.api, this.governanceCurrency));
            return utils_1.newMonetaryAmount(reward.amount.toString(), this.governanceCurrency);
        });
    }
    getRewardEstimate(accountId, amountToLock, blockLockTimeExtension) {
        return __awaiter(this, void 0, void 0, function* () {
            const [userStake, totalStake, blockReward, stakedBalance, currentBlockNumber, minimumBlockPeriod, maxPeriod] = yield Promise.all([
                this.getEscrowStake(accountId),
                this.getEscrowTotalStake(),
                this.getRewardPerBlock(),
                this.getStakedBalance(accountId),
                this.systemAPI.getCurrentBlockNumber(),
                this.api.consts.timestamp.minimumPeriod,
                this.getMaxPeriod(),
            ]);
            return utils_1.estimateReward(this.governanceCurrency, userStake, totalStake, blockReward, stakedBalance, currentBlockNumber, minimumBlockPeriod.toNumber(), maxPeriod.toNumber(), amountToLock, blockLockTimeExtension);
        });
    }
    getEscrowStake(accountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const rawStake = yield this.api.query.escrowRewards.stake([null, accountId]);
            return utils_1.decodeFixedPointType(rawStake);
        });
    }
    getEscrowTotalStake() {
        return __awaiter(this, void 0, void 0, function* () {
            const rawTotalStake = yield this.api.query.escrowRewards.totalStake(null);
            return utils_1.decodeFixedPointType(rawTotalStake);
        });
    }
    getRewardTally(accountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const governanceCurrencyId = utils_1.newCurrencyId(this.api, this.governanceCurrency);
            const rawRewardTally = yield this.api.query.escrowRewards.rewardTally(governanceCurrencyId, [null, accountId]);
            return utils_1.decodeFixedPointType(rawRewardTally);
        });
    }
    getRewardPerToken() {
        return __awaiter(this, void 0, void 0, function* () {
            const governanceCurrencyId = utils_1.newCurrencyId(this.api, this.governanceCurrency);
            const rawRewardPerToken = yield this.api.query.escrowRewards.rewardPerToken(governanceCurrencyId, null);
            return utils_1.decodeFixedPointType(rawRewardPerToken);
        });
    }
    getRewardPerBlock() {
        return __awaiter(this, void 0, void 0, function* () {
            const rawRewardPerBlock = yield this.api.query.escrowAnnuity.rewardPerBlock();
            return utils_1.newMonetaryAmount(rawRewardPerBlock.toString(), this.governanceCurrency);
        });
    }
    getStakedBalance(accountId) {
        return __awaiter(this, void 0, void 0, function* () {
            const rawStakedBalance = yield this.api.query.escrow.locked(accountId);
            return types_1.parseEscrowLockedBalance(this.governanceCurrency, rawStakedBalance);
        });
    }
    getTotalStakedBalance() {
        return __awaiter(this, void 0, void 0, function* () {
            const govCcy = this.governanceCurrency;
            const rawStakedBalances = yield this.api.query.escrow.locked.entries();
            const totalCurrentAmount = rawStakedBalances
                .map(([_, rawStakedBalance]) => types_1.parseEscrowLockedBalance(govCcy, rawStakedBalance).amount)
                .reduce((acc, amount) => acc.add(amount), utils_1.newMonetaryAmount(0, govCcy));
            return totalCurrentAmount;
        });
    }
    votingBalance(accountId, blockNumber) {
        return __awaiter(this, void 0, void 0, function* () {
            const maybeBlockNumber = blockNumber === undefined ? null : blockNumber.toString();
            const balance = yield this.api.rpc.escrow.balanceAt(accountId.toString(), maybeBlockNumber);
            return utils_1.newMonetaryAmount(balance.amount.toString(), utils_1.toVoting(this.governanceCurrency));
        });
    }
    totalVotingSupply(blockNumber) {
        return __awaiter(this, void 0, void 0, function* () {
            const maybeBlockNumber = blockNumber === undefined ? null : blockNumber.toString();
            const supply = yield this.api.rpc.escrow.totalSupply(maybeBlockNumber);
            return utils_1.newMonetaryAmount(supply.amount.toString(), utils_1.toVoting(this.governanceCurrency));
        });
    }
    getSpan() {
        return __awaiter(this, void 0, void 0, function* () {
            return this.api.consts.escrow.span.toBn();
        });
    }
    getMaxPeriod() {
        return __awaiter(this, void 0, void 0, function* () {
            return this.api.consts.escrow.maxPeriod.toBn();
        });
    }
}
exports.DefaultEscrowAPI = DefaultEscrowAPI;
//# sourceMappingURL=escrow.js.map