"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 apollo_link_1 = require("apollo-link");
const apolloLinkContextModule = __importStar(require("apollo-link-context"));
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const types_1 = require("../polkadot/types");
const semver_1 = __importDefault(require("semver"));
const sinon_1 = __importDefault(require("sinon"));
const internal_1 = require("../internal");
const queries_1 = require("../middleware/queries");
const Polymesh_1 = require("../Polymesh");
const mocks_1 = require("../testUtils/mocks");
const types_2 = require("../types");
const utils_1 = require("../types/utils");
const constants_1 = require("../utils/constants");
const utilsConversionModule = __importStar(require("../utils/conversion"));
jest.mock('@polkadot/api', require("../testUtils/mocks/dataSources").mockPolkadotModule('@polkadot/api'));
jest.mock('~/base/Context', require("../testUtils/mocks/dataSources").mockContextModule('~/base/Context'));
jest.mock('apollo-client', require("../testUtils/mocks/dataSources").mockApolloModule('apollo-client'));
jest.mock('~/api/entities/TickerReservation', require("../testUtils/mocks/entities").mockTickerReservationModule('~/api/entities/TickerReservation'));
jest.mock('~/api/entities/Identity', require("../testUtils/mocks/entities").mockIdentityModule('~/api/entities/Identity'));
jest.mock('~/api/entities/Account', require("../testUtils/mocks/entities").mockAccountModule('~/api/entities/Account'));
jest.mock('~/base/Procedure', require("../testUtils/mocks/procedure").mockProcedureModule('~/base/Procedure'));
jest.mock('~/api/entities/SecurityToken', require("../testUtils/mocks/entities").mockSecurityTokenModule('~/api/entities/SecurityToken'));
jest.mock('websocket-as-promised', require("../testUtils/mocks/dataSources").mockWebSocketAsPromisedModule());
describe('Polymesh Class', () => {
    beforeAll(() => {
        mocks_1.dsMockUtils.initMocks();
        mocks_1.entityMockUtils.initMocks();
        mocks_1.procedureMockUtils.initMocks();
    });
    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();
    });
    describe('method: create', () => {
        beforeAll(() => {
            sinon_1.default.stub(apolloLinkContextModule, 'setContext').callsFake(cbFunc => {
                return new apollo_link_1.ApolloLink(cbFunc({}, {}));
            });
        });
        test('should instantiate Context and return a Polymesh instance', () => __awaiter(void 0, void 0, void 0, function* () {
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
            });
            expect(polymesh instanceof Polymesh_1.Polymesh).toBe(true);
        }));
        test('should instantiate Context with a seed and return a Polymesh instance', () => __awaiter(void 0, void 0, void 0, function* () {
            const accountSeed = 'Alice'.padEnd(66, ' ');
            const createStub = mocks_1.dsMockUtils.getContextCreateStub();
            yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountSeed,
            });
            sinon_1.default.assert.calledOnce(createStub);
            sinon_1.default.assert.calledWith(createStub, {
                polymeshApi: mocks_1.dsMockUtils.getApiInstance(),
                middlewareApi: null,
                accountSeed,
                accountUri: undefined,
                accountMnemonic: undefined,
                keyring: undefined,
            });
        }));
        test('should instantiate Context with a keyring and return a Polymesh instance', () => __awaiter(void 0, void 0, void 0, function* () {
            const keyring = {};
            const createStub = mocks_1.dsMockUtils.getContextCreateStub();
            yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                keyring,
            });
            sinon_1.default.assert.calledOnce(createStub);
            sinon_1.default.assert.calledWith(createStub, {
                polymeshApi: mocks_1.dsMockUtils.getApiInstance(),
                middlewareApi: null,
                keyring,
                accountSeed: undefined,
                accountUri: undefined,
                accountMnemonic: undefined,
            });
        }));
        test('should instantiate Context with a ui keyring and return a Polymesh instance', () => __awaiter(void 0, void 0, void 0, function* () {
            const keyring = {};
            const createStub = mocks_1.dsMockUtils.getContextCreateStub();
            yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                keyring: { keyring },
            });
            sinon_1.default.assert.calledOnce(createStub);
            sinon_1.default.assert.calledWith(createStub, {
                polymeshApi: mocks_1.dsMockUtils.getApiInstance(),
                middlewareApi: null,
                keyring: { keyring },
                accountSeed: undefined,
                accountUri: undefined,
                accountMnemonic: undefined,
            });
        }));
        test('should instantiate Context with a uri and return a Polymesh instance', () => __awaiter(void 0, void 0, void 0, function* () {
            const accountUri = '//uri';
            const createStub = mocks_1.dsMockUtils.getContextCreateStub();
            yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri,
            });
            sinon_1.default.assert.calledOnce(createStub);
            sinon_1.default.assert.calledWith(createStub, {
                polymeshApi: mocks_1.dsMockUtils.getApiInstance(),
                middlewareApi: null,
                accountUri,
                accountSeed: undefined,
                accountMnemonic: undefined,
                keyring: undefined,
            });
        }));
        test('should instantiate Context with a mnemonic and return a Polymesh instance', () => __awaiter(void 0, void 0, void 0, function* () {
            const accountMnemonic = 'lorem ipsum dolor sit amet consectetur adipiscing elit nam hendrerit consectetur sagittis';
            const createStub = mocks_1.dsMockUtils.getContextCreateStub();
            yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountMnemonic,
            });
            sinon_1.default.assert.calledOnce(createStub);
            sinon_1.default.assert.calledWith(createStub, {
                polymeshApi: mocks_1.dsMockUtils.getApiInstance(),
                middlewareApi: null,
                accountMnemonic,
                accountSeed: undefined,
                accountUri: undefined,
                keyring: undefined,
            });
        }));
        test('should instantiate Context with middleware credentials and return a Polymesh instance', () => __awaiter(void 0, void 0, void 0, function* () {
            const accountUri = '//uri';
            const createStub = mocks_1.dsMockUtils.getContextCreateStub();
            const middleware = {
                link: 'someLink',
                key: 'someKey',
            };
            mocks_1.dsMockUtils.createApolloQueryStub(queries_1.heartbeat(), true);
            yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri,
                middleware,
            });
            sinon_1.default.assert.calledOnce(createStub);
            sinon_1.default.assert.calledWith(createStub, {
                polymeshApi: mocks_1.dsMockUtils.getApiInstance(),
                middlewareApi: mocks_1.dsMockUtils.getMiddlewareApi(),
                accountUri,
                accountSeed: undefined,
                accountMnemonic: undefined,
                keyring: undefined,
            });
        }));
        test('should throw an error if the Polymesh version does not satisfy the supported version range', () => __awaiter(void 0, void 0, void 0, function* () {
            jest.spyOn(semver_1.default, 'satisfies').mockImplementationOnce(() => false);
            let err;
            try {
                yield Polymesh_1.Polymesh.connect({
                    nodeUrl: 'wss://some.url',
                });
            }
            catch (e) {
                err = e;
            }
            expect(err.message).toBe('Unsupported Polymesh version. Please upgrade the SDK');
            expect(err.data.supportedVersionRange).toBe(constants_1.SUPPORTED_VERSION_RANGE);
        }));
        test('should throw an error if the middleware credentials are incorrect', () => __awaiter(void 0, void 0, void 0, function* () {
            const accountUri = '//uri';
            const middleware = {
                link: 'wrong',
                key: 'alsoWrong',
            };
            mocks_1.dsMockUtils.throwOnMiddlewareQuery(new Error('Forbidden'));
            let err;
            try {
                yield Polymesh_1.Polymesh.connect({
                    nodeUrl: 'wss://some.url',
                    accountUri,
                    middleware,
                });
            }
            catch (e) {
                err = e;
            }
            expect(err.message).toBe('Incorrect middleware URL or API key');
            mocks_1.dsMockUtils.throwOnMiddlewareQuery(new Error('Missing Authentication Token'));
            err = undefined;
            try {
                yield Polymesh_1.Polymesh.connect({
                    nodeUrl: 'wss://some.url',
                    accountUri,
                    middleware,
                });
            }
            catch (e) {
                err = e;
            }
            expect(err.message).toBe('Incorrect middleware URL or API key');
            // other errors are caught when performing queries later on
            mocks_1.dsMockUtils.throwOnMiddlewareQuery(new Error('Anything else'));
            err = undefined;
            try {
                yield Polymesh_1.Polymesh.connect({
                    nodeUrl: 'wss://some.url',
                    accountUri,
                    middleware,
                });
            }
            catch (e) {
                err = e;
            }
            expect(err).toBeUndefined();
        }));
        test('should set an optional signer for the polkadot API', () => __awaiter(void 0, void 0, void 0, function* () {
            const accountSeed = 'Alice'.padEnd(66, ' ');
            const createStub = mocks_1.dsMockUtils.getContextCreateStub();
            const signer = 'signer';
            yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountSeed,
                signer,
            });
            sinon_1.default.assert.calledOnce(createStub);
            sinon_1.default.assert.calledWith(createStub, {
                polymeshApi: mocks_1.dsMockUtils.getApiInstance(),
                middlewareApi: null,
                accountSeed,
                accountUri: undefined,
                accountMnemonic: undefined,
                keyring: undefined,
            });
            sinon_1.default.assert.calledWith(mocks_1.dsMockUtils.getApiInstance().setSigner, signer);
        }));
        test('should throw if Context fails in the connection process', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.dsMockUtils.throwOnApiCreation();
            const nodeUrl = 'wss://some.url';
            const polymeshApiPromise = Polymesh_1.Polymesh.connect({
                nodeUrl,
            });
            return expect(polymeshApiPromise).rejects.toThrow(`Error while connecting to "${nodeUrl}": "Error"`);
        }));
        test('should throw if Polkadot fails in the connection process', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.dsMockUtils.throwOnApiCreation(new Error());
            const nodeUrl = 'wss://some.url';
            const polymeshApiPromise = Polymesh_1.Polymesh.connect({
                nodeUrl,
            });
            return expect(polymeshApiPromise).rejects.toThrow(`Error while connecting to "${nodeUrl}": "The node couldn’t be reached"`);
        }));
        test('should throw if Context create method fails', () => {
            mocks_1.dsMockUtils.throwOnContextCreation();
            const nodeUrl = 'wss://some.url';
            const polymeshApiPromise = Polymesh_1.Polymesh.connect({
                nodeUrl,
            });
            return expect(polymeshApiPromise).rejects.toThrow(`Error while connecting to "${nodeUrl}": "Error"`);
        });
    });
    describe('method: getAccountBalance', () => {
        const fakeBalance = {
            free: new bignumber_js_1.default(100),
            locked: new bignumber_js_1.default(0),
            total: new bignumber_js_1.default(100),
        };
        test('should return the free and locked POLYX balance of the current account', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { balance: fakeBalance } });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
            });
            const result = yield polymesh.getAccountBalance();
            expect(result).toEqual(fakeBalance);
        }));
        test('should return the free and locked POLYX balance of the supplied account', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.entityMockUtils.configureMocks({ accountOptions: { getBalance: fakeBalance } });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
            });
            let result = yield polymesh.getAccountBalance({ account: 'someId' });
            expect(result).toEqual(fakeBalance);
            result = yield polymesh.getAccountBalance({
                account: new internal_1.Account({ address: 'someId ' }, mocks_1.dsMockUtils.getContextInstance()),
            });
            expect(result).toEqual(fakeBalance);
        }));
        test('should allow subscription (with and without a supplied account id)', () => __awaiter(void 0, void 0, void 0, function* () {
            const unsubCallback = 'unsubCallback';
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { balance: fakeBalance } });
            mocks_1.entityMockUtils.configureMocks({ accountOptions: { getBalance: fakeBalance } });
            let accountBalanceStub = mocks_1.dsMockUtils.getContextInstance().getCurrentAccount()
                .getBalance.resolves(unsubCallback);
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
            });
            const callback = (() => 1);
            let result = yield polymesh.getAccountBalance(callback);
            expect(result).toEqual(unsubCallback);
            sinon_1.default.assert.calledWithExactly(accountBalanceStub, callback);
            accountBalanceStub = mocks_1.entityMockUtils.getAccountGetBalanceStub().resolves(unsubCallback);
            const account = 'someId';
            result = yield polymesh.getAccountBalance({ account }, callback);
            expect(result).toEqual(unsubCallback);
            sinon_1.default.assert.calledWithExactly(accountBalanceStub, callback);
        }));
    });
    describe('method: claimClassicTicker', () => {
        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 context = mocks_1.dsMockUtils.getContextInstance();
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
            });
            const args = {
                ticker: 'SOMETICKER',
                ethereumSignature: 'someSig',
            };
            const expectedQueue = 'someQueue';
            mocks_1.procedureMockUtils
                .getPrepareStub()
                .withArgs({ args, transformer: undefined }, context)
                .resolves(expectedQueue);
            const queue = yield polymesh.claimClassicTicker(args);
            expect(queue).toBe(expectedQueue);
        }));
    });
    describe('method: isTickerAvailable', () => {
        beforeAll(() => {
            mocks_1.entityMockUtils.initMocks();
        });
        afterEach(() => {
            mocks_1.entityMockUtils.reset();
        });
        afterAll(() => {
            mocks_1.entityMockUtils.cleanup();
        });
        test('should return true if ticker is available to reserve it', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.entityMockUtils.getTickerReservationDetailsStub().resolves({
                owner: mocks_1.entityMockUtils.getIdentityInstance(),
                expiryDate: new Date(),
                status: types_2.TickerReservationStatus.Free,
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const isTickerAvailable = yield polymesh.isTickerAvailable({ ticker: 'someTicker' });
            expect(isTickerAvailable).toBeTruthy();
        }));
        test('should return false if ticker is not available to reserve it', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.entityMockUtils.getTickerReservationDetailsStub().resolves({
                owner: mocks_1.entityMockUtils.getIdentityInstance(),
                expiryDate: new Date(),
                status: types_2.TickerReservationStatus.Reserved,
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const isTickerAvailable = yield polymesh.isTickerAvailable({ ticker: 'someTicker' });
            expect(isTickerAvailable).toBeFalsy();
        }));
        test('should allow subscription', () => __awaiter(void 0, void 0, void 0, function* () {
            const unsubCallback = 'unsubCallBack';
            mocks_1.entityMockUtils.getTickerReservationDetailsStub().callsFake((cbFunc) => __awaiter(void 0, void 0, void 0, function* () {
                cbFunc({
                    owner: mocks_1.entityMockUtils.getIdentityInstance(),
                    expiryDate: new Date(),
                    status: types_2.TickerReservationStatus.Free,
                });
                return unsubCallback;
            }));
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const callback = sinon_1.default.stub();
            const result = yield polymesh.isTickerAvailable({ ticker: 'someTicker' }, callback);
            expect(result).toBe(unsubCallback);
            sinon_1.default.assert.calledWithExactly(callback, true);
        }));
    });
    describe('method: getTickerReservations', () => {
        beforeAll(() => {
            sinon_1.default.stub(utilsConversionModule, 'signerValueToSignatory');
        });
        afterAll(() => {
            sinon_1.default.restore();
        });
        test('should return a list of ticker reservations if did parameter is set', () => __awaiter(void 0, void 0, void 0, function* () {
            const fakeTicker = 'TEST';
            const did = 'someDid';
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { withSeed: true } });
            mocks_1.dsMockUtils.createQueryStub('asset', 'assetOwnershipRelations', {
                entries: [
                    utils_1.tuple([mocks_1.dsMockUtils.createMockIdentityId(did), mocks_1.dsMockUtils.createMockTicker(fakeTicker)], mocks_1.dsMockUtils.createMockAssetOwnershipRelation('TickerOwned')),
                ],
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const tickerReservations = yield polymesh.getTickerReservations({ owner: did });
            expect(tickerReservations).toHaveLength(1);
            expect(tickerReservations[0].ticker).toBe(fakeTicker);
        }));
        test('should return a list of ticker reservations owned by the Identity', () => __awaiter(void 0, void 0, void 0, function* () {
            const fakeTicker = 'TEST';
            const did = 'someDid';
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { withSeed: true } });
            mocks_1.dsMockUtils.createQueryStub('asset', 'assetOwnershipRelations', {
                entries: [
                    utils_1.tuple([mocks_1.dsMockUtils.createMockIdentityId(did), mocks_1.dsMockUtils.createMockTicker(fakeTicker)], mocks_1.dsMockUtils.createMockAssetOwnershipRelation('TickerOwned')),
                ],
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const tickerReservations = yield polymesh.getTickerReservations();
            expect(tickerReservations).toHaveLength(1);
            expect(tickerReservations[0].ticker).toBe(fakeTicker);
        }));
        test('should filter out tickers with unreadable characters', () => __awaiter(void 0, void 0, void 0, function* () {
            const fakeTicker = 'TEST';
            const unreadableTicker = String.fromCharCode(65533);
            const did = 'someDid';
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { withSeed: true } });
            mocks_1.dsMockUtils.createQueryStub('asset', 'assetOwnershipRelations', {
                entries: [
                    utils_1.tuple([mocks_1.dsMockUtils.createMockIdentityId(did), mocks_1.dsMockUtils.createMockTicker(fakeTicker)], mocks_1.dsMockUtils.createMockAssetOwnershipRelation('TickerOwned')),
                    utils_1.tuple([mocks_1.dsMockUtils.createMockIdentityId(did), mocks_1.dsMockUtils.createMockTicker('someTicker')], mocks_1.dsMockUtils.createMockAssetOwnershipRelation('AssetOwned')),
                    utils_1.tuple([mocks_1.dsMockUtils.createMockIdentityId(did), mocks_1.dsMockUtils.createMockTicker(unreadableTicker)], mocks_1.dsMockUtils.createMockAssetOwnershipRelation('TickerOwned')),
                ],
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const tickerReservations = yield polymesh.getTickerReservations();
            expect(tickerReservations).toHaveLength(1);
            expect(tickerReservations[0].ticker).toBe(fakeTicker);
        }));
    });
    describe('method: getTickerReservation', () => {
        test('should return a specific ticker reservation owned by the Identity', () => __awaiter(void 0, void 0, void 0, function* () {
            const ticker = 'TEST';
            const expiry = new Date();
            mocks_1.dsMockUtils.createQueryStub('asset', 'tickers', {
                returnValue: mocks_1.dsMockUtils.createMockTickerRegistration({
                    owner: mocks_1.dsMockUtils.createMockIdentityId('someDid'),
                    expiry: mocks_1.dsMockUtils.createMockOption(mocks_1.dsMockUtils.createMockMoment(expiry.getTime())),
                }),
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const tickerReservation = yield polymesh.getTickerReservation({ ticker });
            expect(tickerReservation.ticker).toBe(ticker);
        }));
        test('should throw if ticker reservation does not exist', () => __awaiter(void 0, void 0, void 0, function* () {
            const ticker = 'TEST';
            mocks_1.dsMockUtils.createQueryStub('asset', 'tickers', {
                returnValue: mocks_1.dsMockUtils.createMockTickerRegistration({
                    owner: mocks_1.dsMockUtils.createMockIdentityId(),
                    expiry: mocks_1.dsMockUtils.createMockOption(),
                }),
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            return expect(polymesh.getTickerReservation({ ticker })).rejects.toThrow(`There is no reservation for ${ticker} ticker`);
        }));
        test('should throw if ticker is already a token', () => __awaiter(void 0, void 0, void 0, function* () {
            const ticker = 'TEST';
            mocks_1.dsMockUtils.createQueryStub('asset', 'tickers', {
                returnValue: mocks_1.dsMockUtils.createMockTickerRegistration({
                    owner: mocks_1.dsMockUtils.createMockIdentityId('someDid'),
                    expiry: mocks_1.dsMockUtils.createMockOption(),
                }),
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            return expect(polymesh.getTickerReservation({ ticker })).rejects.toThrow(`${ticker} token has been created`);
        }));
    });
    describe('method: getIdentity', () => {
        test('should return an Identity object with the passed did', () => __awaiter(void 0, void 0, void 0, function* () {
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const params = { did: 'testDid' };
            const context = mocks_1.dsMockUtils.getContextInstance();
            const identity = new internal_1.Identity(params, context);
            context.getIdentity.onFirstCall().resolves(identity);
            const result = yield polymesh.getIdentity(params);
            expect(result).toMatchObject(identity);
        }));
    });
    describe('method: getCurrentIdentity', () => {
        test('should return the current Identity', () => __awaiter(void 0, void 0, void 0, function* () {
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const context = mocks_1.dsMockUtils.getContextInstance();
            const [result, currentIdentity] = yield Promise.all([
                polymesh.getCurrentIdentity(),
                context.getCurrentIdentity(),
            ]);
            expect(result).toEqual(currentIdentity);
        }));
    });
    describe('method: getAccount', () => {
        test('should return an Account object with the passed address', () => __awaiter(void 0, void 0, void 0, function* () {
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const params = { address: 'testAddress' };
            const result = polymesh.getAccount(params);
            expect(result.address).toBe(params.address);
        }));
        test('should return the current Account if no address is passed', () => __awaiter(void 0, void 0, void 0, function* () {
            const address = 'someAddress';
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { currentPairAddress: address } });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const result = polymesh.getAccount();
            expect(result.address).toBe(address);
        }));
    });
    describe('method: getAccounts', () => {
        test('should return the list of signer accounts associated to the SDK', () => __awaiter(void 0, void 0, void 0, function* () {
            const accounts = [mocks_1.entityMockUtils.getAccountInstance()];
            mocks_1.dsMockUtils.configureMocks({
                contextOptions: {
                    getAccounts: accounts,
                },
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const result = polymesh.getAccounts();
            expect(result).toEqual(accounts);
        }));
    });
    describe('method: isIdentityValid', () => {
        test('should return true if the supplied Identity exists', () => __awaiter(void 0, void 0, void 0, function* () {
            const did = 'someDid';
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const result = yield polymesh.isIdentityValid({
                identity: mocks_1.entityMockUtils.getIdentityInstance({ did }),
            });
            expect(result).toBe(true);
        }));
        test('should return false if the supplied Identity is invalid', () => __awaiter(void 0, void 0, void 0, function* () {
            const did = 'someDid';
            mocks_1.entityMockUtils.configureMocks({ identityOptions: { exists: false } });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const result = yield polymesh.isIdentityValid({ identity: did });
            expect(result).toBe(false);
        }));
    });
    describe('method: getTransactionFees', () => {
        test('should return the fees associated to the supplied transaction', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { transactionFee: new bignumber_js_1.default(500) } });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const fee = yield polymesh.getTransactionFees({ tag: types_1.TxTags.asset.CreateAsset });
            expect(fee).toEqual(new bignumber_js_1.default(500));
        }));
    });
    describe('method: getTreasuryAccount', () => {
        test('should return the treasury account', () => __awaiter(void 0, void 0, void 0, function* () {
            const treasuryAddress = '5EYCAe5ijAx5xEfZdpCna3grUpY1M9M5vLUH5vpmwV1EnaYR';
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            expect(polymesh.getTreasuryAccount().address).toEqual(treasuryAddress);
        }));
    });
    describe('method: getSecurityTokens', () => {
        beforeAll(() => {
            sinon_1.default.stub(utilsConversionModule, 'signerValueToSignatory');
        });
        afterAll(() => {
            sinon_1.default.restore();
        });
        test('should return a list of security tokens owned by the supplied did', () => __awaiter(void 0, void 0, void 0, function* () {
            const fakeTicker = 'TEST';
            const did = 'someDid';
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { withSeed: true } });
            mocks_1.dsMockUtils.createQueryStub('asset', 'assetOwnershipRelations', {
                entries: [
                    utils_1.tuple([mocks_1.dsMockUtils.createMockIdentityId(did), mocks_1.dsMockUtils.createMockTicker(fakeTicker)], mocks_1.dsMockUtils.createMockAssetOwnershipRelation('AssetOwned')),
                ],
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const securityTokens = yield polymesh.getSecurityTokens({ owner: 'someDid' });
            expect(securityTokens).toHaveLength(1);
            expect(securityTokens[0].ticker).toBe(fakeTicker);
        }));
        test('should return a list of security tokens owned by the current Identity if no did is supplied', () => __awaiter(void 0, void 0, void 0, function* () {
            const fakeTicker = 'TEST';
            const did = 'someDid';
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { withSeed: true } });
            mocks_1.dsMockUtils.createQueryStub('asset', 'assetOwnershipRelations', {
                entries: [
                    utils_1.tuple([mocks_1.dsMockUtils.createMockIdentityId(did), mocks_1.dsMockUtils.createMockTicker(fakeTicker)], mocks_1.dsMockUtils.createMockAssetOwnershipRelation('AssetOwned')),
                ],
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const securityTokens = yield polymesh.getSecurityTokens();
            expect(securityTokens).toHaveLength(1);
            expect(securityTokens[0].ticker).toBe(fakeTicker);
        }));
        test('should filter out tokens whose tickers have unreadable characters', () => __awaiter(void 0, void 0, void 0, function* () {
            const fakeTicker = 'TEST';
            const unreadableTicker = String.fromCharCode(65533);
            const did = 'someDid';
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { withSeed: true } });
            mocks_1.dsMockUtils.createQueryStub('asset', 'assetOwnershipRelations', {
                entries: [
                    utils_1.tuple([mocks_1.dsMockUtils.createMockIdentityId(did), mocks_1.dsMockUtils.createMockTicker(fakeTicker)], mocks_1.dsMockUtils.createMockAssetOwnershipRelation('AssetOwned')),
                    utils_1.tuple([mocks_1.dsMockUtils.createMockIdentityId(did), mocks_1.dsMockUtils.createMockTicker('someTicker')], mocks_1.dsMockUtils.createMockAssetOwnershipRelation('TickerOwned')),
                    utils_1.tuple([mocks_1.dsMockUtils.createMockIdentityId(did), mocks_1.dsMockUtils.createMockTicker(unreadableTicker)], mocks_1.dsMockUtils.createMockAssetOwnershipRelation('AssetOwned')),
                ],
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const securityTokens = yield polymesh.getSecurityTokens();
            expect(securityTokens).toHaveLength(1);
            expect(securityTokens[0].ticker).toBe(fakeTicker);
        }));
    });
    describe('method: transferPolyx', () => {
        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 context = mocks_1.dsMockUtils.getContextInstance();
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const args = {
                to: 'someAccount',
                amount: new bignumber_js_1.default(50),
            };
            const expectedQueue = '';
            mocks_1.procedureMockUtils
                .getPrepareStub()
                .withArgs({ args, transformer: undefined }, context)
                .resolves(expectedQueue);
            const queue = yield polymesh.transferPolyx(args);
            expect(queue).toBe(expectedQueue);
        }));
    });
    describe('method: getSecurityToken', () => {
        test('should return a specific Security Token', () => __awaiter(void 0, void 0, void 0, function* () {
            const ticker = 'TEST';
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const securityToken = yield polymesh.getSecurityToken({ ticker });
            expect(securityToken.ticker).toBe(ticker);
        }));
        test('should throw if the Security Token does not exist', () => __awaiter(void 0, void 0, void 0, function* () {
            const ticker = 'TEST';
            mocks_1.entityMockUtils.configureMocks({ securityTokenOptions: { exists: false } });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            return expect(polymesh.getSecurityToken({ ticker })).rejects.toThrow(`There is no Security Token with ticker "${ticker}"`);
        }));
    });
    describe('method: getNetworkProperties', () => {
        test('should return current network information', () => __awaiter(void 0, void 0, void 0, function* () {
            const name = 'someName';
            const version = 1;
            const fakeResult = {
                name,
                version,
            };
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            mocks_1.dsMockUtils.setRuntimeVersion({ specVersion: mocks_1.dsMockUtils.createMockU32(version) });
            mocks_1.dsMockUtils.createRpcStub('system', 'chain').resolves(mocks_1.dsMockUtils.createMockText(name));
            const result = yield polymesh.getNetworkProperties();
            expect(result).toEqual(fakeResult);
        }));
    });
    describe('method: getTreasuryBalance', () => {
        let fakeBalance;
        beforeAll(() => {
            fakeBalance = {
                free: new bignumber_js_1.default(500000),
                locked: new bignumber_js_1.default(0),
                total: new bignumber_js_1.default(500000),
            };
            mocks_1.entityMockUtils.configureMocks({ accountOptions: { getBalance: fakeBalance } });
        });
        test('should return the POLYX balance of the treasury account', () => __awaiter(void 0, void 0, void 0, function* () {
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
            });
            const result = yield polymesh.getTreasuryBalance();
            expect(result).toEqual(fakeBalance.free);
        }));
        test('should allow subscription', () => __awaiter(void 0, void 0, void 0, function* () {
            const unsubCallback = 'unsubCallback';
            mocks_1.entityMockUtils.getAccountInstance().getBalance.callsFake((cbFunc) => __awaiter(void 0, void 0, void 0, function* () {
                cbFunc(fakeBalance);
                return unsubCallback;
            }));
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
            });
            const callback = sinon_1.default.stub();
            const result = yield polymesh.getTreasuryBalance(callback);
            expect(result).toEqual(unsubCallback);
            sinon_1.default.assert.calledWithExactly(callback, fakeBalance.free);
        }));
    });
    describe('method: onConnectionError', () => {
        test('should call the supplied listener when the event is emitted and return an unsubscribe callback', () => __awaiter(void 0, void 0, void 0, function* () {
            const polkadot = mocks_1.dsMockUtils.getApiInstance();
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const callback = sinon_1.default.stub();
            const unsub = polymesh.onConnectionError(callback);
            polkadot.emit('error');
            polkadot.emit('disconnected');
            unsub();
            polkadot.emit('error');
            sinon_1.default.assert.calledOnce(callback);
        }));
    });
    describe('method: registerIdentity', () => {
        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 context = mocks_1.dsMockUtils.getContextInstance();
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const args = {
                targetAccount: 'someTarget',
            };
            const expectedQueue = 'someQueue';
            mocks_1.procedureMockUtils
                .getPrepareStub()
                .withArgs({ args, transformer: undefined }, context)
                .resolves(expectedQueue);
            const queue = yield polymesh.registerIdentity(args);
            expect(queue).toBe(expectedQueue);
        }));
    });
    describe('method: onDisconnect', () => {
        test('should call the supplied listener when the event is emitted and return an unsubscribe callback', () => __awaiter(void 0, void 0, void 0, function* () {
            const polkadot = mocks_1.dsMockUtils.getApiInstance();
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
            });
            const callback = sinon_1.default.stub();
            const unsub = polymesh.onDisconnect(callback);
            polkadot.emit('disconnected');
            polkadot.emit('error');
            unsub();
            polkadot.emit('disconnected');
            sinon_1.default.assert.calledOnce(callback);
        }));
    });
    describe('method: getLatestBlock', () => {
        test('should return the latest block number', () => __awaiter(void 0, void 0, void 0, function* () {
            const blockNumber = new bignumber_js_1.default(100);
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { withSeed: true, latestBlock: blockNumber } });
            mocks_1.dsMockUtils.createApolloQueryStub(queries_1.heartbeat(), true);
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
                middleware: {
                    link: 'someLink',
                    key: 'someKey',
                },
            });
            const result = yield polymesh.getLatestBlock();
            expect(result).toEqual(blockNumber);
        }));
    });
    describe('method: disconnect', () => {
        test('should call the underlying disconnect function', () => __awaiter(void 0, void 0, void 0, function* () {
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
                middleware: {
                    link: 'someLink',
                    key: 'someKey',
                },
            });
            yield polymesh.disconnect();
            sinon_1.default.assert.calledOnce(mocks_1.dsMockUtils.getContextInstance().disconnect);
        }));
    });
    describe('method: getNetworkVersion', () => {
        test('should return the network version', () => __awaiter(void 0, void 0, void 0, function* () {
            const networkVersion = '1.0.0';
            mocks_1.dsMockUtils.configureMocks({ contextOptions: { withSeed: true, networkVersion } });
            mocks_1.dsMockUtils.createApolloQueryStub(queries_1.heartbeat(), true);
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
                middleware: {
                    link: 'someLink',
                    key: 'someKey',
                },
            });
            const result = yield polymesh.getNetworkVersion();
            expect(result).toEqual(networkVersion);
        }));
    });
    describe('method: addSigner', () => {
        test('should call the underlying addPair function', () => __awaiter(void 0, void 0, void 0, function* () {
            const pair = {
                address: '5EYCAe5ijAx5xEfZdpCna3grUpY1M9M5vLUH5vpmwV1EnaYR',
                publicKey: 'someKey',
                meta: {},
            };
            mocks_1.dsMockUtils.configureMocks({
                contextOptions: {
                    addPair: pair,
                },
            });
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
                middleware: {
                    link: 'someLink',
                    key: 'someKey',
                },
            });
            let params = { accountSeed: '0x1' };
            let account = polymesh.addSigner(params);
            expect(account.address).toBe(pair.address);
            params = { accountMnemonic: 'something' };
            account = polymesh.addSigner(params);
            expect(account.address).toBe(pair.address);
            params = { accountUri: '//Something' };
            account = polymesh.addSigner(params);
            expect(account.address).toBe(pair.address);
        }));
    });
    describe('method: setSigner', () => {
        test('should call the underlying setPair function', () => __awaiter(void 0, void 0, void 0, function* () {
            const polymesh = yield Polymesh_1.Polymesh.connect({
                nodeUrl: 'wss://some.url',
                accountUri: '//uri',
                middleware: {
                    link: 'someLink',
                    key: 'someKey',
                },
            });
            const address = 'address';
            polymesh.setSigner(address);
            sinon_1.default.assert.calledWith(mocks_1.dsMockUtils.getContextInstance().setPair, address);
        }));
    });
});
//# sourceMappingURL=Polymesh.js.map