"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
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 });
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const sinon_1 = __importDefault(require("sinon"));
const utils_1 = require("../utils");
const internal_1 = require("../../../internal");
const mocks_1 = require("../../../testUtils/mocks");
const types_1 = require("../../../types");
const utilsConversionModule = __importStar(require("../../../utils/conversion"));
jest.mock('~/api/entities/NumberedPortfolio', require("../../../testUtils/mocks/entities").mockNumberedPortfolioModule('~/api/entities/NumberedPortfolio'));
jest.mock('~/api/entities/Identity', require("../../../testUtils/mocks/entities").mockIdentityModule('~/api/entities/Identity'));
jest.mock('~/api/entities/KnownPermissionGroup', require("../../../testUtils/mocks/entities").mockKnownPermissionGroupModule('~/api/entities/KnownPermissionGroup'));
jest.mock('~/api/entities/Account', require("../../../testUtils/mocks/entities").mockAccountModule('~/api/entities/Account'));
jest.mock('~/api/entities/SecurityToken', require("../../../testUtils/mocks/entities").mockSecurityTokenModule('~/api/entities/SecurityToken'));
jest.mock('~/api/entities/TickerReservation', require("../../../testUtils/mocks/entities").mockTickerReservationModule('~/api/entities/TickerReservation'));
// NOTE uncomment in Governance v2 upgrade
// jest.mock(
//   '~/api/entities/Proposal',
//   require('~/testUtils/mocks/entities').mockProposalModule('~/api/entities/Proposal')
// );
// describe('assertProposalUnlocked', () => {
//   const pipId = new BigNumber(10);
//   const mockAddress = 'someAddress';
//   const details = ({
//     transaction: 'someModule.someMethod',
//   } as unknown) as ProposalDetails;
//   let mockContext: Mocked<Context>;
//   beforeAll(() => {
//     dsMockUtils.initMocks({
//       contextOptions: {
//         currentPairAddress: mockAddress,
//       },
//     });
//     entityMockUtils.initMocks();
//   });
//   beforeEach(() => {
//     mockContext = dsMockUtils.getContextInstance();
//   });
//   afterEach(() => {
//     entityMockUtils.reset();
//     dsMockUtils.reset();
//   });
//   afterAll(() => {
//     entityMockUtils.cleanup();
//     dsMockUtils.cleanup();
//   });
//   test('should throw an error if the proposal is not in pending state', async () => {
//     entityMockUtils.configureMocks({
//       proposalOptions: {
//         getDetails: {
//           ...details,
//           lastState: ProposalState.Killed,
//         },
//       },
//     });
//     let error;
//     try {
//       await assertProposalUnlocked(pipId, mockContext);
//     } catch (err) {
//       error = err;
//     }
//     expect(error.message).toBe('The proposal must be in pending state');
//   });
//   test('should throw an error if the proposal is not in the cool off period', async () => {
//     entityMockUtils.configureMocks({
//       proposalOptions: {
//         getDetails: {
//           ...details,
//           lastState: ProposalState.Pending,
//         },
//         getStage: ProposalStage.Open,
//       },
//     });
//     let error;
//     try {
//       await assertProposalUnlocked(pipId, mockContext);
//     } catch (err) {
//       error = err;
//     }
//     expect(error.message).toBe('The proposal must be in its cool-off period');
//   });
//   test('should not throw an error if the proposal is unlocked', async () => {
//     entityMockUtils.configureMocks({
//       proposalOptions: {
//         getDetails: {
//           ...details,
//           lastState: ProposalState.Pending,
//         },
//         getStage: ProposalStage.CoolOff,
//       },
//     });
//     const result = await assertProposalUnlocked(pipId, mockContext);
//     expect(result).toBeUndefined();
//   });
// });
describe('assertInstructionValid', () => {
    const latestBlock = new bignumber_js_1.default(100);
    let mockContext;
    let instruction;
    beforeAll(() => {
        mocks_1.dsMockUtils.initMocks({
            contextOptions: {
                latestBlock,
            },
        });
        mocks_1.entityMockUtils.initMocks();
    });
    beforeEach(() => {
        mockContext = mocks_1.dsMockUtils.getContextInstance();
    });
    afterEach(() => {
        mocks_1.entityMockUtils.reset();
        mocks_1.dsMockUtils.reset();
    });
    afterAll(() => {
        mocks_1.entityMockUtils.cleanup();
        mocks_1.dsMockUtils.cleanup();
    });
    test('should throw an error if instruction is not in pending state', () => {
        mocks_1.entityMockUtils.configureMocks({
            instructionOptions: {
                details: {
                    status: types_1.InstructionStatus.Executed,
                },
            },
        });
        instruction = mocks_1.entityMockUtils.getInstructionInstance();
        return expect(utils_1.assertInstructionValid(instruction, mockContext)).rejects.toThrow('The Instruction must be in pending state');
    });
    test('should throw an error if the instruction can not be modified', () => __awaiter(void 0, void 0, void 0, function* () {
        const endBlock = new bignumber_js_1.default(10);
        mocks_1.entityMockUtils.configureMocks({
            instructionOptions: {
                details: {
                    status: types_1.InstructionStatus.Pending,
                    type: types_1.InstructionType.SettleOnBlock,
                    tradeDate: new Date('10/10/2010'),
                    endBlock,
                },
            },
        });
        instruction = mocks_1.entityMockUtils.getInstructionInstance();
        let error;
        try {
            yield utils_1.assertInstructionValid(instruction, mockContext);
        }
        catch (err) {
            error = err;
        }
        expect(error.message).toBe('The Instruction cannot be modified; it has already reached its end block');
        expect(error.data.currentBlock).toBe(latestBlock);
        expect(error.data.endBlock).toEqual(endBlock);
    }));
    test('should not throw an error', () => __awaiter(void 0, void 0, void 0, function* () {
        mocks_1.entityMockUtils.configureMocks({
            instructionOptions: {
                details: {
                    status: types_1.InstructionStatus.Pending,
                    type: types_1.InstructionType.SettleOnAffirmation,
                },
            },
        });
        instruction = mocks_1.entityMockUtils.getInstructionInstance();
        let result = yield utils_1.assertInstructionValid(instruction, mockContext);
        expect(result).toBeUndefined();
        mocks_1.entityMockUtils.configureMocks({
            instructionOptions: {
                details: {
                    status: types_1.InstructionStatus.Pending,
                    type: types_1.InstructionType.SettleOnBlock,
                    endBlock: new bignumber_js_1.default(1000000),
                },
            },
        });
        instruction = mocks_1.entityMockUtils.getInstructionInstance();
        result = yield utils_1.assertInstructionValid(instruction, mockContext);
        expect(result).toBeUndefined();
    }));
});
describe('assertPortfolioExists', () => {
    test("should throw an error if the portfolio doesn't exist", () => __awaiter(void 0, void 0, void 0, function* () {
        mocks_1.entityMockUtils.configureMocks({ numberedPortfolioOptions: { exists: false } });
        const context = mocks_1.dsMockUtils.getContextInstance();
        let error;
        try {
            yield utils_1.assertPortfolioExists({ did: 'someDid', number: new bignumber_js_1.default(10) }, context);
        }
        catch (err) {
            error = err;
        }
        expect(error.message).toBe("The Portfolio doesn't exist");
    }));
    test('should not throw an error if the portfolio exists', () => __awaiter(void 0, void 0, void 0, function* () {
        mocks_1.entityMockUtils.configureMocks({ numberedPortfolioOptions: { exists: true } });
        const context = mocks_1.dsMockUtils.getContextInstance();
        let error;
        try {
            yield utils_1.assertPortfolioExists({ did: 'someDid', number: new bignumber_js_1.default(10) }, context);
            yield utils_1.assertPortfolioExists({ did: 'someDid' }, context);
        }
        catch (err) {
            error = err;
        }
        expect(error).toBeUndefined();
    }));
});
describe('assertSecondaryKeys', () => {
    let signerToSignerValueStub;
    beforeAll(() => {
        signerToSignerValueStub = sinon_1.default.stub(utilsConversionModule, 'signerToSignerValue');
    });
    test('should not throw an error if all signers are secondary keys', () => __awaiter(void 0, void 0, void 0, function* () {
        const address = 'someAddress';
        const secondaryKeys = [
            {
                signer: mocks_1.entityMockUtils.getAccountInstance({ address }),
                permissions: {
                    tokens: null,
                    transactions: null,
                    transactionGroups: [],
                    portfolios: null,
                },
            },
        ];
        const signerValues = [{ type: types_1.SignerType.Account, value: address }];
        signerToSignerValueStub.returns(signerValues[0]);
        const result = utils_1.assertSecondaryKeys(signerValues, secondaryKeys);
        expect(result).toBeUndefined();
    }));
    test('should throw an error if one of the Signers is not a Secondary Key for the Identity', () => {
        const address = 'someAddress';
        const secondaryKeys = [
            {
                signer: mocks_1.entityMockUtils.getAccountInstance({ address }),
                permissions: {
                    tokens: null,
                    transactions: null,
                    transactionGroups: [],
                    portfolios: null,
                },
            },
        ];
        const signerValues = [{ type: types_1.SignerType.Account, value: 'otherAddress' }];
        signerToSignerValueStub.returns({ type: types_1.SignerType.Account, value: address });
        let error;
        try {
            utils_1.assertSecondaryKeys(signerValues, secondaryKeys);
        }
        catch (err) {
            error = err;
        }
        expect(error.message).toBe('One of the Signers is not a Secondary Key for the Identity');
        expect(error.data.missing).toEqual([signerValues[0].value]);
    });
});
describe('assertCaTargetsValid', () => {
    let mockContext;
    beforeAll(() => {
        mocks_1.dsMockUtils.initMocks();
    });
    beforeEach(() => {
        mockContext = mocks_1.dsMockUtils.getContextInstance();
        mocks_1.dsMockUtils.setConstMock('corporateAction', 'maxTargetIds', {
            returnValue: mocks_1.dsMockUtils.createMockU32(1),
        });
    });
    afterEach(() => {
        mocks_1.dsMockUtils.reset();
    });
    afterAll(() => {
        mocks_1.dsMockUtils.cleanup();
    });
    test('should throw an error if there are more target identities than the maximum', () => __awaiter(void 0, void 0, void 0, function* () {
        expect(() => utils_1.assertCaTargetsValid({ identities: ['someDid', 'otherDid'], treatment: types_1.TargetTreatment.Include }, mockContext)).toThrow('Too many target Identities');
    }));
    test('should not throw an error if the number of target identities is appropriate', () => __awaiter(void 0, void 0, void 0, function* () {
        expect(() => utils_1.assertCaTargetsValid({ identities: ['someDid'], treatment: types_1.TargetTreatment.Include }, mockContext)).not.toThrow();
    }));
});
describe('assertCaTaxWithholdingsValid', () => {
    let mockContext;
    beforeAll(() => {
        mocks_1.dsMockUtils.initMocks();
    });
    beforeEach(() => {
        mockContext = mocks_1.dsMockUtils.getContextInstance();
        mocks_1.dsMockUtils.setConstMock('corporateAction', 'maxDidWhts', {
            returnValue: mocks_1.dsMockUtils.createMockU32(1),
        });
    });
    afterEach(() => {
        mocks_1.dsMockUtils.reset();
    });
    afterAll(() => {
        mocks_1.dsMockUtils.cleanup();
    });
    test('should throw an error if there are more target identities than the maximum', () => __awaiter(void 0, void 0, void 0, function* () {
        expect(() => utils_1.assertCaTaxWithholdingsValid([
            { identity: 'someDid', percentage: new bignumber_js_1.default(15) },
            { identity: 'otherDid', percentage: new bignumber_js_1.default(16) },
        ], mockContext)).toThrow('Too many tax withholding entries');
    }));
    test('should not throw an error if the number of target identities is appropriate', () => __awaiter(void 0, void 0, void 0, function* () {
        expect(() => utils_1.assertCaTaxWithholdingsValid([{ identity: 'someDid', percentage: new bignumber_js_1.default(15) }], mockContext)).not.toThrow();
    }));
});
describe('assertCaCheckpointValid', () => {
    beforeAll(() => {
        mocks_1.dsMockUtils.initMocks();
    });
    afterEach(() => {
        mocks_1.dsMockUtils.reset();
    });
    afterAll(() => {
        mocks_1.dsMockUtils.cleanup();
    });
    test('should throw an error if date is in the past', () => __awaiter(void 0, void 0, void 0, function* () {
        let checkpoint = new Date(new Date().getTime() - 100000);
        let error;
        try {
            yield utils_1.assertCaCheckpointValid(checkpoint);
        }
        catch (err) {
            error = err;
        }
        expect(error.message).toBe('Checkpoint date must be in the future');
        checkpoint = new Date(new Date().getTime() + 100000);
        return expect(utils_1.assertCaCheckpointValid(checkpoint)).resolves.not.toThrow();
    }));
    test('should throw an error if the checkpoint does not exist', () => __awaiter(void 0, void 0, void 0, function* () {
        let checkpoint = mocks_1.entityMockUtils.getCheckpointInstance({
            exists: false,
        });
        let error;
        try {
            yield utils_1.assertCaCheckpointValid(checkpoint);
        }
        catch (err) {
            error = err;
        }
        expect(error.message).toBe("Checkpoint doesn't exist");
        checkpoint = mocks_1.entityMockUtils.getCheckpointInstance({
            exists: true,
        });
        return expect(utils_1.assertCaCheckpointValid(checkpoint)).resolves.not.toThrow();
    }));
    test('should throw an error if checkpoint schedule no longer exists', () => __awaiter(void 0, void 0, void 0, function* () {
        const checkpoint = mocks_1.entityMockUtils.getCheckpointScheduleInstance({
            exists: false,
        });
        let error;
        try {
            yield utils_1.assertCaCheckpointValid(checkpoint);
        }
        catch (err) {
            error = err;
        }
        expect(error.message).toBe("Checkpoint Schedule doesn't exist");
    }));
});
describe('assertCaCheckpointValid', () => {
    beforeAll(() => {
        mocks_1.dsMockUtils.initMocks();
    });
    afterEach(() => {
        mocks_1.dsMockUtils.reset();
    });
    afterAll(() => {
        mocks_1.dsMockUtils.cleanup();
    });
    test('should throw an error if the payment date is earlier than the Checkpoint date', () => __awaiter(void 0, void 0, void 0, function* () {
        const date = new Date(new Date().getTime());
        let checkpoint = date;
        const paymentDate = new Date(new Date().getTime() - 100000);
        const expiryDate = new Date();
        let error;
        try {
            yield utils_1.assertDistributionDatesValid(checkpoint, paymentDate, expiryDate);
        }
        catch (err) {
            error = err;
        }
        expect(error.message).toBe('Payment date must be after the Checkpoint date');
        checkpoint = mocks_1.entityMockUtils.getCheckpointScheduleInstance({
            details: {
                nextCheckpointDate: date,
            },
        });
        try {
            yield utils_1.assertDistributionDatesValid(checkpoint, paymentDate, expiryDate);
        }
        catch (err) {
            error = err;
        }
        expect(error.message).toBe('Payment date must be after the Checkpoint date');
    }));
    test('should throw an error if the expiry date is earlier than the Checkpoint date', () => __awaiter(void 0, void 0, void 0, function* () {
        const date = new Date(new Date().getTime() - 100000);
        let checkpoint = date;
        const paymentDate = new Date(new Date().getTime());
        const expiryDate = new Date(new Date().getTime() - 200000);
        let error;
        try {
            yield utils_1.assertDistributionDatesValid(checkpoint, paymentDate, expiryDate);
        }
        catch (err) {
            error = err;
        }
        expect(error.message).toBe('Expiry date must be after the Checkpoint date');
        checkpoint = mocks_1.entityMockUtils.getCheckpointScheduleInstance({
            details: {
                nextCheckpointDate: date,
            },
        });
        try {
            yield utils_1.assertDistributionDatesValid(checkpoint, paymentDate, expiryDate);
        }
        catch (err) {
            error = err;
        }
        expect(error.message).toBe('Expiry date must be after the Checkpoint date');
        checkpoint = mocks_1.entityMockUtils.getCheckpointScheduleInstance({
            details: {
                nextCheckpointDate: new Date(new Date().getTime() - 300000),
            },
        });
        return expect(utils_1.assertDistributionDatesValid(checkpoint, paymentDate, expiryDate)).resolves.not.toThrow();
    }));
});
describe('assertRequirementsNotTooComplex', () => {
    let mockContext;
    beforeEach(() => {
        mockContext = mocks_1.dsMockUtils.getContextInstance();
    });
    beforeAll(() => {
        mocks_1.dsMockUtils.initMocks();
    });
    afterEach(() => {
        mocks_1.dsMockUtils.reset();
    });
    afterAll(() => {
        mocks_1.dsMockUtils.cleanup();
    });
    test('should throw an error if the complexity sumatory is greater than max condition complexity', () => __awaiter(void 0, void 0, void 0, function* () {
        mocks_1.dsMockUtils.setConstMock('complianceManager', 'maxConditionComplexity', {
            returnValue: mocks_1.dsMockUtils.createMockU32(2),
        });
        expect(() => utils_1.assertRequirementsNotTooComplex([
            {
                type: types_1.ConditionType.IsPresent,
                target: types_1.ConditionTarget.Both,
                trustedClaimIssuers: ['issuer'],
            },
            {
                type: types_1.ConditionType.IsAnyOf,
                claims: [mocks_1.dsMockUtils.createMockClaim(), mocks_1.dsMockUtils.createMockClaim()],
                target: types_1.ConditionTarget.Sender,
            },
        ], 1, mockContext)).toThrow('Compliance Requirement complexity limit exceeded');
    }));
    test('should not throw an error if the complexity is less than the max condition complexity', () => __awaiter(void 0, void 0, void 0, function* () {
        mocks_1.dsMockUtils.setConstMock('complianceManager', 'maxConditionComplexity', {
            returnValue: mocks_1.dsMockUtils.createMockU32(10),
        });
        expect(() => utils_1.assertRequirementsNotTooComplex([{ type: types_1.ConditionType.IsPresent, target: types_1.ConditionTarget.Receiver }], 1, mockContext)).not.toThrow();
    }));
});
describe('authorization request validations', () => {
    let mockContext;
    let target;
    let issuer;
    let expiry;
    beforeEach(() => {
        mockContext = mocks_1.dsMockUtils.getContextInstance();
        issuer = mocks_1.entityMockUtils.getIdentityInstance();
        target = mocks_1.entityMockUtils.getIdentityInstance();
        mocks_1.dsMockUtils.createQueryStub('identity', 'authorizations', {
            returnValue: mocks_1.dsMockUtils.createMockOption(mocks_1.dsMockUtils.createMockAuthorization({
                /* eslint-disable @typescript-eslint/naming-convention */
                authorization_data: mocks_1.dsMockUtils.createMockAuthorizationData('RotatePrimaryKey'),
                auth_id: 1,
                authorized_by: 'someDid',
                expiry: mocks_1.dsMockUtils.createMockOption(),
                /* eslint-enable @typescript-eslint/naming-convention */
            })),
        });
    });
    afterEach(() => {
        mocks_1.dsMockUtils.reset();
        mocks_1.entityMockUtils.reset();
    });
    afterAll(() => {
        mocks_1.dsMockUtils.cleanup();
        mocks_1.entityMockUtils.cleanup();
    });
    describe('assertAuthorizationRequestValid', () => {
        test('should throw with an expired request', () => __awaiter(void 0, void 0, void 0, function* () {
            const auth = mocks_1.entityMockUtils.getAuthorizationRequestInstance({ isExpired: true });
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'The Authorization Request has expired',
            });
            expect(error).toEqual(expectedError);
        }));
        test('should throw with an Authorization that does not exist', () => __awaiter(void 0, void 0, void 0, function* () {
            const auth = mocks_1.entityMockUtils.getAuthorizationRequestInstance({ exists: false });
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'The Authorization Request no longer exists',
            });
            expect(error).toEqual(expectedError);
        }));
    });
    describe('assertPrimaryKeyRotationAuthorizationValid', () => {
        const data = { type: types_1.AuthorizationType.RotatePrimaryKey };
        test('should not throw with a valid request', () => __awaiter(void 0, void 0, void 0, function* () {
            const goodTarget = mocks_1.entityMockUtils.getAccountInstance({ getIdentity: null });
            const auth = new internal_1.AuthorizationRequest({ authId: new bignumber_js_1.default(1), target: goodTarget, issuer, expiry, data }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            expect(error).toBe(undefined);
        }));
        test('should throw not with target that is an Identity', () => __awaiter(void 0, void 0, void 0, function* () {
            const badTarget = mocks_1.entityMockUtils.getIdentityInstance();
            const auth = new internal_1.AuthorizationRequest({ authId: new bignumber_js_1.default(1), target: badTarget, issuer, expiry, data }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'An Identity can not become the primary key of another Identity',
            });
            expect(error).toEqual(expectedError);
        }));
    });
    describe('assertAttestPrimaryKeyAuthorizationValid', () => {
        const data = {
            type: types_1.AuthorizationType.AttestPrimaryKeyRotation,
            value: '',
        };
        test('should not throw with a valid request', () => __awaiter(void 0, void 0, void 0, function* () {
            const mockIssuer = mocks_1.entityMockUtils.getIdentityInstance({ isCddProvider: true });
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer: mockIssuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            expect(error).toBe(undefined);
        }));
        test('should throw with non CDD provider Issuer', () => __awaiter(void 0, void 0, void 0, function* () {
            const mockIssuer = mocks_1.entityMockUtils.getIdentityInstance({ isCddProvider: false });
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer: mockIssuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'Issuer must be a CDD provider',
            });
            expect(error).toEqual(expectedError);
        }));
    });
    describe('assertTransferTickerAuthorizationValid', () => {
        test('should not throw with a valid request', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.entityMockUtils.configureMocks({
                tickerReservationOptions: { details: { status: types_1.TickerReservationStatus.Reserved } },
            });
            const data = {
                type: types_1.AuthorizationType.TransferTicker,
                value: 'TICKER',
            };
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            expect(error).toBe(undefined);
        }));
        test('should throw with an unreserved ticker', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.entityMockUtils.configureMocks({
                tickerReservationOptions: { details: { status: types_1.TickerReservationStatus.Free } },
            });
            const data = {
                type: types_1.AuthorizationType.TransferTicker,
                value: 'TICKER',
            };
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'The Ticker is not reserved',
            });
            expect(error).toEqual(expectedError);
        }));
        test('should throw with an already used ticker', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.entityMockUtils.configureMocks({
                tickerReservationOptions: { details: { status: types_1.TickerReservationStatus.TokenCreated } },
            });
            const data = {
                type: types_1.AuthorizationType.TransferTicker,
                value: 'TICKER',
            };
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'The Ticker has already been used to create an Asset',
            });
            expect(error).toEqual(expectedError);
        }));
    });
    describe('assertTransferAssetOwnershipAuthorizationValid', () => {
        test('should not throw with a valid request', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.entityMockUtils.configureMocks({ securityTokenOptions: { exists: true } });
            const data = {
                type: types_1.AuthorizationType.TransferAssetOwnership,
                value: 'TICKER',
            };
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                issuer,
                target,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            expect(error).toBe(undefined);
        }));
        test('should throw with a Asset that does not exist', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.entityMockUtils.configureMocks({ securityTokenOptions: { exists: false } });
            const data = {
                type: types_1.AuthorizationType.TransferAssetOwnership,
                value: 'TICKER',
            };
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                issuer,
                target,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'The Asset does not exist',
            });
            expect(error).toEqual(expectedError);
        }));
    });
    describe('PortfolioCustody', () => {
        test('should throw with a valid request', () => __awaiter(void 0, void 0, void 0, function* () {
            const data = {
                type: types_1.AuthorizationType.PortfolioCustody,
                value: mocks_1.entityMockUtils.getNumberedPortfolioInstance(),
            };
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            expect(error).toBe(undefined);
        }));
    });
    describe('assertJoinIdentityAuthorizationValid', () => {
        const permissions = {
            tokens: null,
            transactions: null,
            transactionGroups: [],
            portfolios: null,
        };
        const data = {
            type: types_1.AuthorizationType.JoinIdentity,
            value: permissions,
        };
        test('should not throw with a valid request', () => __awaiter(void 0, void 0, void 0, function* () {
            const mockTarget = mocks_1.entityMockUtils.getAccountInstance({ getIdentity: null });
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target: mockTarget,
                issuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            expect(error).toBe(undefined);
        }));
        test('should throw when the issuer lacks a valid CDD', () => __awaiter(void 0, void 0, void 0, function* () {
            const mockIssuer = mocks_1.entityMockUtils.getIdentityInstance({ hasValidCdd: false });
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer: mockIssuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'Issuing Identity does not have a valid CDD claim',
            });
            expect(error).toEqual(expectedError);
        }));
        test('should throw when the target is an Identity', () => __awaiter(void 0, void 0, void 0, function* () {
            const mockIssuer = mocks_1.entityMockUtils.getIdentityInstance({ hasValidCdd: true });
            const mockTarget = mocks_1.entityMockUtils.getIdentityInstance();
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target: mockTarget,
                issuer: mockIssuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'The target cannot be an Identity',
            });
            expect(error).toEqual(expectedError);
        }));
        test('should throw if the target already has an Identity', () => __awaiter(void 0, void 0, void 0, function* () {
            const mockIssuer = mocks_1.entityMockUtils.getIdentityInstance({ hasValidCdd: true });
            const mockTarget = mocks_1.entityMockUtils.getAccountInstance({
                getIdentity: mocks_1.entityMockUtils.getIdentityInstance(),
            });
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target: mockTarget,
                issuer: mockIssuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'The target Account already has an associated Identity',
            });
            expect(error).toEqual(expectedError);
        }));
    });
    describe('assertAddRelayerPayingKeyAuthroizationValid', () => {
        const allowance = new bignumber_js_1.default(100);
        test('should not throw with a valid request', () => __awaiter(void 0, void 0, void 0, function* () {
            const subsidizer = mocks_1.entityMockUtils.getAccountInstance({
                getIdentity: mocks_1.entityMockUtils.getIdentityInstance({ hasValidCdd: true }),
            });
            const beneficiary = mocks_1.entityMockUtils.getAccountInstance({ getIdentity: target });
            const subsidy = {
                beneficiary,
                subsidizer,
                allowance,
                remaining: allowance,
            };
            const data = {
                type: types_1.AuthorizationType.AddRelayerPayingKey,
                value: subsidy,
            };
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            expect(error).toBe(undefined);
        }));
        test('should throw with a beneficiary that does not have a CDD Claim', () => __awaiter(void 0, void 0, void 0, function* () {
            const subsidizer = mocks_1.entityMockUtils.getAccountInstance({
                getIdentity: mocks_1.entityMockUtils.getIdentityInstance(),
            });
            const beneficiary = mocks_1.entityMockUtils.getAccountInstance({
                getIdentity: mocks_1.entityMockUtils.getIdentityInstance({ hasValidCdd: false }),
            });
            const subsidy = {
                beneficiary,
                subsidizer,
                allowance,
                remaining: allowance,
            };
            const data = {
                type: types_1.AuthorizationType.AddRelayerPayingKey,
                value: subsidy,
            };
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'Beneficiary Account does not have a valid CDD Claim',
            });
            expect(error).toEqual(expectedError);
        }));
        test('should throw with a Subsidizer that does not have a CDD Claim', () => __awaiter(void 0, void 0, void 0, function* () {
            const beneficiary = mocks_1.entityMockUtils.getAccountInstance({
                getIdentity: mocks_1.entityMockUtils.getIdentityInstance({ hasValidCdd: true }),
            });
            // getIdentityInstance modifies the prototype, which prevents two mocks from returning different values
            const subsidizer = {
                getIdentity: () => {
                    return { hasValidCdd: () => false };
                },
            };
            const subsidy = {
                beneficiary,
                subsidizer,
                allowance,
                remaining: allowance,
            };
            const data = {
                type: types_1.AuthorizationType.AddRelayerPayingKey,
                value: subsidy,
            };
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'Subsidizer Account does not have a valid CDD Claim',
            });
            expect(error).toEqual(expectedError);
        }));
        test('should throw with a beneficiary that does not have an Identity', () => __awaiter(void 0, void 0, void 0, function* () {
            const subsidizer = mocks_1.entityMockUtils.getAccountInstance({
                getIdentity: mocks_1.entityMockUtils.getIdentityInstance({ hasValidCdd: false }),
            });
            const beneficiary = mocks_1.entityMockUtils.getAccountInstance({ getIdentity: null });
            const subsidy = {
                beneficiary,
                subsidizer,
                allowance,
                remaining: allowance,
            };
            const data = {
                type: types_1.AuthorizationType.AddRelayerPayingKey,
                value: subsidy,
            };
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'Beneficiary Account does not have an Identity',
            });
            expect(error).toEqual(expectedError);
        }));
        test('should throw with a Subsidizer that does not have an Identity', () => __awaiter(void 0, void 0, void 0, function* () {
            const beneficiary = mocks_1.entityMockUtils.getAccountInstance({
                getIdentity: mocks_1.entityMockUtils.getIdentityInstance({ hasValidCdd: true }),
            });
            // getIdentityInstance modifies the prototype, which prevents two mocks from returning different values
            const subsidizer = {
                getIdentity: () => null,
            };
            const subsidy = {
                beneficiary,
                subsidizer,
                allowance,
                remaining: allowance,
            };
            const data = {
                type: types_1.AuthorizationType.AddRelayerPayingKey,
                value: subsidy,
            };
            const auth = new internal_1.AuthorizationRequest({
                authId: new bignumber_js_1.default(1),
                target,
                issuer,
                expiry,
                data,
            }, mockContext);
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid(auth, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new internal_1.PolymeshError({
                code: types_1.ErrorCode.UnmetPrerequisite,
                message: 'Subsidizer Account does not have an Identity',
            });
            expect(error).toEqual(expectedError);
        }));
    });
    describe('unreachable code', () => {
        test('with an any assertion', () => __awaiter(void 0, void 0, void 0, function* () {
            let error;
            try {
                yield utils_1.assertAuthorizationRequestValid({
                    data: { type: 'FAKE_TYPE' },
                    isExpired: () => false,
                    exists: () => true,
                }, mockContext);
            }
            catch (err) {
                error = err;
            }
            const expectedError = new utils_1.UnreachableCaseError({ type: 'FAKE_TYPE' });
            expect(error).toEqual(expectedError);
        }));
    });
});
describe('Unreachable error case', () => {
    test('should throw error if called via type assertion', () => __awaiter(void 0, void 0, void 0, function* () {
        const message = 'Should never happen';
        const error = new utils_1.UnreachableCaseError(message);
        expect(error.message).toEqual(`Unreachable case: "${message}"`);
    }));
});
describe('createAuthorizationResolver', () => {
    beforeAll(() => {
        mocks_1.dsMockUtils.initMocks();
        mocks_1.entityMockUtils.initMocks();
    });
    const filterRecords = () => [
        { event: { data: [undefined, undefined, undefined, '3', undefined] } },
    ];
    test('should return a function that creates an AuthorizationRequest', () => __awaiter(void 0, void 0, void 0, function* () {
        const mockContext = mocks_1.dsMockUtils.getContextInstance();
        const authData = {
            type: types_1.AuthorizationType.RotatePrimaryKey,
        };
        const resolver = utils_1.createAuthorizationResolver(authData, mocks_1.entityMockUtils.getIdentityInstance(), mocks_1.entityMockUtils.getIdentityInstance(), null, mockContext);
        const authRequest = resolver({
            filterRecords: filterRecords,
        });
        expect(authRequest.authId).toEqual(new bignumber_js_1.default(3));
    }));
    test('should return a function that creates an AuthorizationRequest with a PostTransaction Authorization', () => __awaiter(void 0, void 0, void 0, function* () {
        const mockContext = mocks_1.dsMockUtils.getContextInstance();
        const authData = {
            type: types_1.AuthorizationType.RotatePrimaryKey,
        };
        const postTransaction = new internal_1.PostTransactionValue(() => authData);
        yield postTransaction.run({});
        const resolver = utils_1.createAuthorizationResolver(postTransaction, mocks_1.entityMockUtils.getIdentityInstance(), mocks_1.entityMockUtils.getIdentityInstance(), null, mockContext);
        const authRequest = resolver({
            filterRecords: filterRecords,
        });
        expect(authRequest.authId).toEqual(new bignumber_js_1.default(3));
    }));
});
//# sourceMappingURL=utils.js.map