"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.consumeJoinOrRotateAuthorization = exports.prepareStorage = exports.getAuthorization = exports.prepareConsumeJoinOrRotateAuthorization = void 0;
const utils_1 = require("./utils");
const internal_1 = require("../../internal");
const types_1 = require("../../types");
const conversion_1 = require("../../utils/conversion");
/**
 * @hidden
 *
 * Consumes JoinIdentity, RotatePrimaryKey and RotatePrimaryKeyToSecondaryKey Authorizations
 */
function prepareConsumeJoinOrRotateAuthorization(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const { context: { polymeshApi: { tx: { identity }, }, }, storage: { calledByTarget }, context, } = this;
        const { authRequest, accept } = args;
        const { target, authId, issuer, data: { type }, } = authRequest;
        if (![
            types_1.AuthorizationType.JoinIdentity,
            types_1.AuthorizationType.RotatePrimaryKeyToSecondary,
            types_1.AuthorizationType.RotatePrimaryKey,
        ].includes(type)) {
            throw new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnexpectedError,
                message: `Unrecognized auth type: "${type}" for consumeJoinOrRotateAuthorization method`,
            });
        }
        const rawAuthId = conversion_1.bigNumberToU64(authId, context);
        if (!accept) {
            const baseArgs = {};
            if (calledByTarget) {
                baseArgs.paidForBy = issuer;
            }
            this.addTransaction(Object.assign(Object.assign({ transaction: identity.removeAuthorization }, baseArgs), { args: [
                    conversion_1.signerValueToSignatory(conversion_1.signerToSignerValue(target), context),
                    rawAuthId,
                    conversion_1.booleanToBool(calledByTarget, context),
                ] }));
            return;
        }
        yield utils_1.assertAuthorizationRequestValid(authRequest, context);
        if (type === types_1.AuthorizationType.JoinIdentity) {
            this.addTransaction({
                transaction: identity.joinIdentityAsKey,
                paidForBy: issuer,
                args: [rawAuthId],
            });
        }
        else {
            const transaction = type === types_1.AuthorizationType.RotatePrimaryKey
                ? identity.acceptPrimaryKey
                : identity.rotatePrimaryKeyToSecondary;
            this.addTransaction({
                transaction,
                paidForBy: issuer,
                args: [rawAuthId, null],
            });
        }
    });
}
exports.prepareConsumeJoinOrRotateAuthorization = prepareConsumeJoinOrRotateAuthorization;
/**
 * @hidden
 *
 * - If the auth is being accepted, we check that the caller is the target
 * - If the auth is being rejected, we check that the caller is either the target or the issuer
 */
function getAuthorization({ authRequest, accept }) {
    return __awaiter(this, void 0, void 0, function* () {
        const { issuer } = authRequest;
        const { storage: { signingAccount, calledByTarget }, } = this;
        let hasRoles = calledByTarget;
        const { data: { type }, } = authRequest;
        /*
         * when accepting a JoinIdentity request, you don't need permissions (and can't have them by definition),
         *   you just need to be the target
         */
        if (accept) {
            return {
                roles: hasRoles || `"${type}" Authorization Requests must be accepted by the target Account`,
            };
        }
        const identity = yield signingAccount.getIdentity();
        /*
         * if the target is removing the auth request and they don't have an Identity,
         *   no permissions are required
         */
        if (calledByTarget && !identity) {
            return {
                roles: true,
            };
        }
        // both the issuer and the target can remove the authorization request
        hasRoles = hasRoles || !!(identity === null || identity === void 0 ? void 0 : identity.isEqual(issuer));
        return {
            roles: hasRoles ||
                `"${type}" Authorization Requests can only be removed by the issuer Identity or the target Account`,
            permissions: {
                transactions: [types_1.TxTags.identity.RemoveAuthorization],
            },
        };
    });
}
exports.getAuthorization = getAuthorization;
/**
 * @hidden
 */
function prepareStorage({ authRequest: { target } }) {
    return __awaiter(this, void 0, void 0, function* () {
        const { context } = this;
        // JoinIdentity Authorizations always target an Account
        const targetAccount = target;
        const signingAccount = context.getSigningAccount();
        const calledByTarget = targetAccount.isEqual(signingAccount);
        return {
            signingAccount,
            calledByTarget,
        };
    });
}
exports.prepareStorage = prepareStorage;
/**
 * @hidden
 */
const consumeJoinOrRotateAuthorization = () => new internal_1.Procedure(prepareConsumeJoinOrRotateAuthorization, getAuthorization, prepareStorage);
exports.consumeJoinOrRotateAuthorization = consumeJoinOrRotateAuthorization;
//# sourceMappingURL=consumeJoinOrRotateAuthorization.js.map