"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 internal_1 = require("../../../../internal");
const queries_1 = require("../../../../middleware/queries");
const mocks_1 = require("../../../../testUtils/mocks");
const types_1 = require("../../../../types");
const utilsConversionModule = __importStar(require("../../../../utils/conversion"));
jest.mock('~/api/entities/Identity', require("../../../../testUtils/mocks/entities").mockIdentityModule('~/api/entities/Identity'));
jest.mock('~/api/entities/SecurityToken', require("../../../../testUtils/mocks/entities").mockSecurityTokenModule('~/api/entities/SecurityToken'));
jest.mock('~/api/entities/DefaultPortfolio', require("../../../../testUtils/mocks/entities").mockDefaultPortfolioModule('~/api/entities/DefaultPortfolio'));
jest.mock('~/api/entities/Venue', require("../../../../testUtils/mocks/entities").mockVenueModule('~/api/entities/Venue'));
jest.mock('~/base/Procedure', require("../../../../testUtils/mocks/procedure").mockProcedureModule('~/base/Procedure'));
describe('Sto class', () => {
    let context;
    beforeAll(() => {
        mocks_1.dsMockUtils.initMocks();
        mocks_1.entityMockUtils.initMocks();
        mocks_1.procedureMockUtils.initMocks();
    });
    beforeEach(() => {
        context = mocks_1.dsMockUtils.getContextInstance();
    });
    afterEach(() => {
        mocks_1.dsMockUtils.reset();
        mocks_1.entityMockUtils.reset();
        mocks_1.procedureMockUtils.reset();
    });
    afterAll(() => {
        mocks_1.dsMockUtils.cleanup();
        mocks_1.entityMockUtils.cleanup();
        mocks_1.procedureMockUtils.cleanup();
    });
    test('should extend Entity', () => {
        expect(internal_1.Sto.prototype instanceof internal_1.Entity).toBe(true);
    });
    describe('constructor', () => {
        test('should assign ticker and id to instance', () => {
            const ticker = 'SOMETICKER';
            const id = new bignumber_js_1.default(1);
            const sto = new internal_1.Sto({ id, ticker }, context);
            expect(sto.ticker).toBe(ticker);
            expect(sto.id).toEqual(id);
        });
    });
    describe('method: isUniqueIdentifiers', () => {
        test('should return true if the object conforms to the interface', () => {
            expect(internal_1.Sto.isUniqueIdentifiers({ id: new bignumber_js_1.default(1), ticker: 'symbol' })).toBe(true);
            expect(internal_1.Sto.isUniqueIdentifiers({})).toBe(false);
            expect(internal_1.Sto.isUniqueIdentifiers({ id: new bignumber_js_1.default(1) })).toBe(false);
            expect(internal_1.Sto.isUniqueIdentifiers({ id: 1 })).toBe(false);
        });
    });
    describe('method: details', () => {
        const ticker = 'FAKETICKER';
        const id = new bignumber_js_1.default(1);
        const someDid = 'someDid';
        const name = 'someSto';
        const otherDid = 'otherDid';
        const raisingCurrency = 'USD';
        const amount = new bignumber_js_1.default(1000);
        const price = new bignumber_js_1.default(100);
        const remaining = new bignumber_js_1.default(700);
        const date = new Date();
        const minInvestmentValue = new bignumber_js_1.default(1);
        const rawFundraiser = mocks_1.dsMockUtils.createMockOption(mocks_1.dsMockUtils.createMockFundraiser({
            /* eslint-disable @typescript-eslint/naming-convention */
            creator: mocks_1.dsMockUtils.createMockIdentityId(someDid),
            offering_portfolio: mocks_1.dsMockUtils.createMockPortfolioId({
                did: mocks_1.dsMockUtils.createMockIdentityId(someDid),
                kind: mocks_1.dsMockUtils.createMockPortfolioKind('Default'),
            }),
            offering_asset: mocks_1.dsMockUtils.createMockTicker(ticker),
            raising_portfolio: mocks_1.dsMockUtils.createMockPortfolioId({
                did: mocks_1.dsMockUtils.createMockIdentityId(otherDid),
                kind: mocks_1.dsMockUtils.createMockPortfolioKind('Default'),
            }),
            raising_asset: mocks_1.dsMockUtils.createMockTicker(raisingCurrency),
            tiers: [
                mocks_1.dsMockUtils.createMockFundraiserTier({
                    total: mocks_1.dsMockUtils.createMockBalance(amount.toNumber()),
                    price: mocks_1.dsMockUtils.createMockBalance(price.toNumber()),
                    remaining: mocks_1.dsMockUtils.createMockBalance(remaining.toNumber()),
                }),
            ],
            venue_id: mocks_1.dsMockUtils.createMockU64(1),
            start: mocks_1.dsMockUtils.createMockMoment(date.getTime()),
            end: mocks_1.dsMockUtils.createMockOption(mocks_1.dsMockUtils.createMockMoment(date.getTime())),
            status: mocks_1.dsMockUtils.createMockFundraiserStatus('Live'),
            minimum_investment: mocks_1.dsMockUtils.createMockBalance(minInvestmentValue.toNumber()),
            /* eslint-enable @typescript-eslint/naming-convention */
        }));
        const rawName = mocks_1.dsMockUtils.createMockFundraiserName(name);
        let sto;
        beforeEach(() => {
            context = mocks_1.dsMockUtils.getContextInstance();
            sto = new internal_1.Sto({ ticker, id }, context);
        });
        test('should return details for a security token offering', () => __awaiter(void 0, void 0, void 0, function* () {
            const fakeResult = {
                creator: new internal_1.Identity({ did: someDid }, context),
                name,
                offeringPortfolio: new internal_1.DefaultPortfolio({ did: someDid }, context),
                raisingPortfolio: new internal_1.DefaultPortfolio({ did: otherDid }, context),
                raisingCurrency,
                tiers: [
                    {
                        amount: amount.shiftedBy(-6),
                        price: price.shiftedBy(-6),
                        remaining: remaining.shiftedBy(-6),
                    },
                ],
                venue: new internal_1.Venue({ id: new bignumber_js_1.default(1) }, context),
                start: date,
                end: date,
                status: {
                    sale: types_1.StoSaleStatus.Live,
                    timing: types_1.StoTimingStatus.Expired,
                    balance: types_1.StoBalanceStatus.Residual,
                },
                minInvestment: minInvestmentValue.shiftedBy(-6),
                totalAmount: amount.shiftedBy(-6),
                totalRemaining: remaining.shiftedBy(-6),
            };
            mocks_1.dsMockUtils.createQueryStub('sto', 'fundraisers', {
                returnValue: rawFundraiser,
            });
            mocks_1.dsMockUtils.createQueryStub('sto', 'fundraiserNames', {
                returnValue: rawName,
            });
            const details = yield sto.details();
            expect(details).toEqual(fakeResult);
        }));
        test('should throw if security token offering does not exist', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.dsMockUtils.createQueryStub('sto', 'fundraiserNames', {
                returnValue: mocks_1.dsMockUtils.createMockFundraiserName(),
            });
            mocks_1.dsMockUtils.createQueryStub('sto', 'fundraisers', {
                returnValue: mocks_1.dsMockUtils.createMockOption(),
            });
            return expect(sto.details()).rejects.toThrow('STO no longer exists');
        }));
        test('should allow subscription', () => __awaiter(void 0, void 0, void 0, function* () {
            const unsubCallback = 'unsubCallBack';
            mocks_1.dsMockUtils.createQueryStub('sto', 'fundraiserNames', {
                returnValue: rawName,
            });
            mocks_1.dsMockUtils.createQueryStub('sto', 'fundraisers').callsFake((_a, _b, cbFunc) => __awaiter(void 0, void 0, void 0, function* () {
                cbFunc(rawFundraiser, rawName);
                return unsubCallback;
            }));
            const callback = sinon_1.default.stub();
            const result = yield sto.details(callback);
            sinon_1.default.stub(utilsConversionModule, 'fundraiserToStoDetails').returns({});
            expect(result).toBe(unsubCallback);
            sinon_1.default.assert.calledWithExactly(callback, sinon_1.default.match({}));
        }));
    });
    describe('method: close', () => {
        test('should prepare the procedure with the correct arguments and context, and return the resulting transaction queue', () => __awaiter(void 0, void 0, void 0, function* () {
            const ticker = 'SOMETICKER';
            const id = new bignumber_js_1.default(1);
            const sto = new internal_1.Sto({ id, ticker }, context);
            const args = {
                ticker,
                id,
            };
            const expectedQueue = 'someQueue';
            mocks_1.procedureMockUtils
                .getPrepareStub()
                .withArgs({ args, transformer: undefined }, context)
                .resolves(expectedQueue);
            const queue = yield sto.close();
            expect(queue).toBe(expectedQueue);
        }));
    });
    describe('method: modifyTimes', () => {
        test('should prepare the procedure with the correct arguments and context, and return the resulting transaction queue', () => __awaiter(void 0, void 0, void 0, function* () {
            const ticker = 'SOMETICKER';
            const id = new bignumber_js_1.default(1);
            const sto = new internal_1.Sto({ id, ticker }, context);
            const now = new Date();
            const start = new Date(now.getTime() + 100000);
            const end = new Date(start.getTime() + 100000);
            const args = {
                ticker,
                id,
                start,
                end,
            };
            const expectedQueue = 'someQueue';
            mocks_1.procedureMockUtils
                .getPrepareStub()
                .withArgs({ args, transformer: undefined }, context)
                .resolves(expectedQueue);
            const queue = yield sto.modifyTimes({
                start,
                end,
            });
            expect(queue).toBe(expectedQueue);
        }));
    });
    describe('method: getInvestments', () => {
        test('should return a list of investors', () => __awaiter(void 0, void 0, void 0, function* () {
            const ticker = 'SOMETICKER';
            const id = new bignumber_js_1.default(1);
            const sto = new internal_1.Sto({ id, ticker }, context);
            const did = 'someDid';
            const offeringToken = 'TICKER';
            const raiseToken = 'USD';
            const offeringTokenAmount = new bignumber_js_1.default(10000);
            const raiseTokenAmount = new bignumber_js_1.default(1000);
            const items = [
                {
                    investor: did,
                    offeringToken,
                    raiseToken,
                    offeringTokenAmount: offeringTokenAmount.toNumber(),
                    raiseTokenAmount: raiseTokenAmount.toNumber(),
                    datetime: '2020-10-10',
                },
            ];
            /* eslint-disable @typescript-eslint/naming-convention */
            const investmentQueryResponse = {
                totalCount: 1,
                items,
            };
            /* eslint-enabled @typescript-eslint/naming-convention */
            mocks_1.dsMockUtils.createApolloQueryStub(queries_1.heartbeat(), true);
            mocks_1.dsMockUtils.createApolloQueryStub(queries_1.investments({
                stoId: id.toNumber(),
                ticker,
                count: 5,
                skip: 0,
            }), {
                investments: investmentQueryResponse,
            });
            let result = yield sto.getInvestments({
                size: 5,
                start: 0,
            });
            const { data } = result;
            expect(data[0].investor.did).toBe(did);
            expect(data[0].soldAmount).toEqual(offeringTokenAmount.div(Math.pow(10, 6)));
            expect(data[0].investedAmount).toEqual(raiseTokenAmount.div(Math.pow(10, 6)));
            mocks_1.dsMockUtils.createApolloQueryStub(queries_1.investments({
                stoId: id.toNumber(),
                ticker,
                count: undefined,
                skip: undefined,
            }), {
                investments: {
                    totalCount: 0,
                    items: null,
                },
            });
            result = yield sto.getInvestments();
            expect(result.data).toEqual([]);
            expect(result.next).toBeNull();
        }));
    });
    describe('method: freeze', () => {
        test('should prepare the procedure and return the resulting transaction queue', () => __awaiter(void 0, void 0, void 0, function* () {
            const ticker = 'SOMETICKER';
            const id = new bignumber_js_1.default(1);
            const sto = new internal_1.Sto({ id, ticker }, context);
            const expectedQueue = 'someQueue';
            mocks_1.procedureMockUtils
                .getPrepareStub()
                .withArgs({ args: { ticker, id, freeze: true }, transformer: undefined }, context)
                .resolves(expectedQueue);
            const queue = yield sto.freeze();
            expect(queue).toBe(expectedQueue);
        }));
    });
    describe('method: unfreeze', () => {
        test('should prepare the procedure and return the resulting transaction queue', () => __awaiter(void 0, void 0, void 0, function* () {
            const ticker = 'SOMETICKER';
            const id = new bignumber_js_1.default(1);
            const sto = new internal_1.Sto({ id, ticker }, context);
            const expectedQueue = 'someQueue';
            mocks_1.procedureMockUtils
                .getPrepareStub()
                .withArgs({ args: { ticker, id, freeze: false }, transformer: undefined }, context)
                .resolves(expectedQueue);
            const queue = yield sto.unfreeze();
            expect(queue).toBe(expectedQueue);
        }));
    });
    describe('method: invest', () => {
        test('should prepare the procedure with the correct arguments and context, and return the resulting transaction queue', () => __awaiter(void 0, void 0, void 0, function* () {
            const ticker = 'SOMETICKER';
            const id = new bignumber_js_1.default(1);
            const sto = new internal_1.Sto({ id, ticker }, context);
            const did = 'someDid';
            const purchasePortfolio = new internal_1.DefaultPortfolio({ did }, context);
            const fundingPortfolio = new internal_1.DefaultPortfolio({ did }, context);
            const purchaseAmount = new bignumber_js_1.default(10);
            const args = {
                ticker,
                id,
                purchasePortfolio,
                fundingPortfolio,
                purchaseAmount,
            };
            const expectedQueue = 'someQueue';
            mocks_1.procedureMockUtils
                .getPrepareStub()
                .withArgs({ args, transformer: undefined }, context)
                .resolves(expectedQueue);
            const queue = yield sto.invest({
                purchasePortfolio,
                fundingPortfolio,
                purchaseAmount,
            });
            expect(queue).toBe(expectedQueue);
        }));
    });
    describe('method: exists', () => {
        test('should return whether the Offering exists', () => __awaiter(void 0, void 0, void 0, function* () {
            const sto = new internal_1.Sto({ ticker: 'SOME_TICKER', id: new bignumber_js_1.default(1) }, context);
            mocks_1.dsMockUtils.createQueryStub('sto', 'fundraisers', {
                returnValue: mocks_1.dsMockUtils.createMockOption(mocks_1.dsMockUtils.createMockFundraiser()),
            });
            let result = yield sto.exists();
            expect(result).toBe(true);
            mocks_1.dsMockUtils.createQueryStub('sto', 'fundraisers', {
                returnValue: mocks_1.dsMockUtils.createMockOption(),
            });
            result = yield sto.exists();
            expect(result).toBe(false);
        }));
    });
    describe('method: toJson', () => {
        test('should return a human readable version of the entity', () => {
            const sto = new internal_1.Sto({ ticker: 'SOME_TICKER', id: new bignumber_js_1.default(1) }, context);
            expect(sto.toJson()).toEqual({
                id: '1',
                ticker: 'SOME_TICKER',
            });
        });
    });
});
//# sourceMappingURL=index.js.map