"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 mocks_1 = require("../../../testUtils/mocks");
const entities_1 = require("../../../testUtils/mocks/entities");
const types_1 = require("../../../types");
const utilsConversionModule = __importStar(require("../../../utils/conversion"));
jest.mock('~/api/entities/NumberedPortfolio', require("../../../testUtils/mocks/entities").mockNumberedPortfolioModule('~/api/entities/NumberedPortfolio'));
// 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 = entities_1.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 = entities_1.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 = entities_1.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 = entities_1.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 emties');
    }));
    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();
    }));
});
//# sourceMappingURL=utils.js.map