From 3fd83d60ae85450b3dea1a3ef06c7e284e5abd41 Mon Sep 17 00:00:00 2001 From: Shuffledex Date: Tue, 20 Oct 2020 14:06:45 -0300 Subject: [PATCH] feat: getPortfolio method --- src/api/entities/Identity/Portfolios.ts | 44 +++++++++- .../entities/Identity/__tests__/Portfolios.ts | 83 ++++++++++++++++++- 2 files changed, 124 insertions(+), 3 deletions(-) diff --git a/src/api/entities/Identity/Portfolios.ts b/src/api/entities/Identity/Portfolios.ts index cdb19553c8..e5e6780e77 100644 --- a/src/api/entities/Identity/Portfolios.ts +++ b/src/api/entities/Identity/Portfolios.ts @@ -1,6 +1,46 @@ -import { Identity, Namespace } from '~/api/entities'; +import BigNumber from 'bignumber.js'; + +import { DefaultPortfolio, Identity, Namespace, NumberedPortfolio } from '~/api/entities'; +import { PolymeshError } from '~/base'; +import { ErrorCode } from '~/types'; +import { bytesToString, numberToU64, stringToIdentityId } from '~/utils'; /** * Handles all Portfolio related functionality on the Identity side */ -export class Portfolios extends Namespace {} +export class Portfolios extends Namespace { + /** + * Retrieve a numbered Portfolio or the default Portfolio if Portfolio Id is not passed + * + * @param args.porfolioId - optional, default to the default portfolio + */ + public async getPortfolio(porfolioId?: BigNumber): Promise { + const { + context, + context: { + polymeshApi: { + query: { portfolio }, + }, + }, + } = this; + + const { did } = await context.getCurrentIdentity(); + + if (!porfolioId) { + return new DefaultPortfolio({ did }, context); + } + + const identityId = stringToIdentityId(did, context); + const rawPortolioNumber = numberToU64(porfolioId, context); + const rawPortfolioName = await portfolio.portfolios(identityId, rawPortolioNumber); + + if (!bytesToString(rawPortfolioName)) { + throw new PolymeshError({ + code: ErrorCode.InvalidUuid, + message: "The Portfolio doesn't exist", + }); + } + + return new NumberedPortfolio({ id: porfolioId, did }, context); + } +} diff --git a/src/api/entities/Identity/__tests__/Portfolios.ts b/src/api/entities/Identity/__tests__/Portfolios.ts index 1572a8fb4d..c6502e835c 100644 --- a/src/api/entities/Identity/__tests__/Portfolios.ts +++ b/src/api/entities/Identity/__tests__/Portfolios.ts @@ -1,9 +1,90 @@ -import { Namespace } from '~/api/entities'; +import { Bytes, u64 } from '@polkadot/types'; +import BigNumber from 'bignumber.js'; +import { IdentityId } from 'polymesh-types/types'; +import sinon from 'sinon'; + +import { DefaultPortfolio, Identity, Namespace, NumberedPortfolio } from '~/api/entities'; +import { Context } from '~/base'; +import { dsMockUtils } from '~/testUtils/mocks'; +import { Mocked } from '~/testUtils/types'; +import * as utilsModule from '~/utils'; import { Portfolios } from '../Portfolios'; describe('Portfolios class', () => { + const did = 'someDid'; + let context: Mocked; + let portfolios: Portfolios; + let identity: Identity; + let stringToIdentityIdStub: sinon.SinonStub<[string, Context], IdentityId>; + let numberToU64Stub: sinon.SinonStub<[number | BigNumber, Context], u64>; + let bytesToStringStub: sinon.SinonStub<[Bytes], string>; + + beforeAll(() => { + dsMockUtils.initMocks(); + stringToIdentityIdStub = sinon.stub(utilsModule, 'stringToIdentityId'); + numberToU64Stub = sinon.stub(utilsModule, 'numberToU64'); + bytesToStringStub = sinon.stub(utilsModule, 'bytesToString'); + }); + + beforeEach(() => { + context = dsMockUtils.getContextInstance(); + identity = new Identity({ did }, context); + portfolios = new Portfolios(identity, context); + }); + + afterEach(() => { + dsMockUtils.reset(); + }); + + afterAll(() => { + dsMockUtils.cleanup(); + }); + test('should extend namespace', () => { expect(Portfolios.prototype instanceof Namespace).toBe(true); }); + + describe('method: getPortfolio', () => { + test('should return the default portfolio for the current identity', async () => { + const result = await portfolios.getPortfolio(); + expect(result instanceof DefaultPortfolio).toBe(true); + expect(result.owner.did).toEqual(did); + }); + + test('should return a numbered portfolio', async () => { + const portfolioId = new BigNumber(1); + const portfolioName = 'someName'; + + dsMockUtils.createQueryStub('portfolio', 'portfolios', { + returnValue: dsMockUtils.createMockBytes(portfolioName), + }); + + stringToIdentityIdStub.returns(dsMockUtils.createMockIdentityId(did)); + numberToU64Stub.returns(dsMockUtils.createMockU64(portfolioId.toNumber())); + bytesToStringStub.returns(portfolioName); + + const result = await portfolios.getPortfolio(portfolioId); + + expect(result instanceof NumberedPortfolio).toBe(true); + expect((result as NumberedPortfolio).id).toEqual(portfolioId); + }); + + test("should throw an error ir portfolio doesn't exist", async () => { + const portfolioId = new BigNumber(0); + const portfolioName = ''; + + dsMockUtils.createQueryStub('portfolio', 'portfolios', { + returnValue: dsMockUtils.createMockBytes(portfolioName), + }); + + stringToIdentityIdStub.returns(dsMockUtils.createMockIdentityId(did)); + numberToU64Stub.returns(dsMockUtils.createMockU64(portfolioId.toNumber())); + bytesToStringStub.returns(portfolioName); + + return expect(portfolios.getPortfolio(portfolioId)).rejects.toThrow( + "The Portfolio doesn't exist" + ); + }); + }); });