From 4a2e3b295e3731b48385a47895087133fb3bdaea Mon Sep 17 00:00:00 2001 From: Shuffledex Date: Mon, 28 Sep 2020 14:43:37 -0300 Subject: [PATCH] feat: adapt canTransfer to portfolio logic. MSDK-292 --- src/api/entities/SecurityToken/Transfers.ts | 43 ++--- .../SecurityToken/__tests__/Transfers.ts | 38 +---- src/api/procedures/__tests__/issueTokens.ts | 13 +- src/api/procedures/__tests__/transferToken.ts | 154 ------------------ src/api/procedures/index.ts | 1 - src/api/procedures/issueTokens.ts | 15 +- src/api/procedures/transferToken.ts | 72 -------- src/middleware/types.ts | 4 - src/polkadot/polymesh/definitions.ts | 23 ++- src/polkadot/types.ts | 3 - src/types/index.ts | 13 +- src/utils/__tests__/index.ts | 67 +++++++- src/utils/index.ts | 24 +++ 13 files changed, 137 insertions(+), 333 deletions(-) delete mode 100644 src/api/procedures/__tests__/transferToken.ts delete mode 100644 src/api/procedures/transferToken.ts diff --git a/src/api/entities/SecurityToken/Transfers.ts b/src/api/entities/SecurityToken/Transfers.ts index 9b6e5995f3..8a64cf8a83 100644 --- a/src/api/entities/SecurityToken/Transfers.ts +++ b/src/api/entities/SecurityToken/Transfers.ts @@ -2,13 +2,14 @@ import BigNumber from 'bignumber.js'; import { CanTransferResult } from 'polymesh-types/types'; import { Identity, Namespace, SecurityToken } from '~/api/entities'; -import { toggleFreezeTransfers, transferToken, TransferTokenParams } from '~/api/procedures'; +import { toggleFreezeTransfers } from '~/api/procedures'; import { TransactionQueue } from '~/base'; -import { SubCallback, TransferStatus, UnsubCallback } from '~/types'; +import { KnownPortfolioKind, SubCallback, TransferStatus, UnsubCallback } from '~/types'; import { boolToBoolean, canTransferResultToTransferStatus, numberToBalance, + portfolioIdToMeshPortfolioId, signerToString, stringToAccountId, stringToIdentityId, @@ -76,7 +77,7 @@ export class Transfers extends Namespace { } /** - * Check whether it is possible to transfer a certain amount of this asset between two Identities + * Check whether it is possible to transfer a certain amount of this asset between two portfolios * * @param args.from - sender Identity (optional, defaults to the current Identity) * @param args.to - receiver Identity @@ -91,21 +92,11 @@ export class Transfers extends Namespace { return this._canTransfer({ from, to, amount }); } - /** - * Check whether it is possible to mint a certain amount of this asset - * - * @param args.to - receiver Identity - * @param args.amount - amount of tokens to mint - */ - public canMint(args: { to: string | Identity; amount: BigNumber }): Promise { - return this._canTransfer({ ...args, from: null }); - } - /** * @hidden */ private async _canTransfer(args: { - from?: null | string | Identity; + from: string | Identity; to: string | Identity; amount: BigNumber; }): Promise { @@ -119,11 +110,8 @@ export class Transfers extends Namespace { const { from, to, amount } = args; - let fromDid = null; - if (from) { - fromDid = stringToIdentityId(signerToString(from), context); - } - const toDid = signerToString(to); + const fromDid = stringToIdentityId(signerToString(from), context); + const toDid = stringToIdentityId(signerToString(to), context); /* * The RPC requires a sender account ID (although it's not being used at the moment). We use the current account @@ -134,23 +122,14 @@ export class Transfers extends Namespace { // eslint-disable-next-line @typescript-eslint/no-explicit-any const res: CanTransferResult = await (rpc as any).asset.canTransfer( stringToAccountId(senderAddress, context), + null, + portfolioIdToMeshPortfolioId({ did: fromDid, kind: KnownPortfolioKind.Default }, context), + null, + portfolioIdToMeshPortfolioId({ did: toDid, kind: KnownPortfolioKind.Default }, context), stringToTicker(ticker, context), - fromDid, - stringToIdentityId(toDid, context), numberToBalance(amount, context) ); return canTransferResultToTransferStatus(res); } - - /** - * Transfer an amount of the token to another Identity. - */ - public async transfer(args: TransferTokenParams): Promise> { - const { - parent: { ticker }, - context, - } = this; - return transferToken.prepare({ ticker, ...args }, context); - } } diff --git a/src/api/entities/SecurityToken/__tests__/Transfers.ts b/src/api/entities/SecurityToken/__tests__/Transfers.ts index c264c90d5e..dd5397df31 100644 --- a/src/api/entities/SecurityToken/__tests__/Transfers.ts +++ b/src/api/entities/SecurityToken/__tests__/Transfers.ts @@ -5,7 +5,7 @@ import { IdentityId, Ticker } from 'polymesh-types/types'; import sinon, { SinonStub } from 'sinon'; import { Namespace } from '~/api/entities'; -import { toggleFreezeTransfers, transferToken } from '~/api/procedures'; +import { toggleFreezeTransfers } from '~/api/procedures'; import { Params } from '~/api/procedures/toggleFreezeTransfers'; import { Context, TransactionQueue } from '~/base'; import { dsMockUtils, entityMockUtils } from '~/testUtils/mocks'; @@ -201,40 +201,4 @@ describe('Transfers class', () => { expect(result).toBe(TransferStatus.Success); }); }); - - describe('method: canMint', () => { - test('should return a status value representing whether the minting can be made', async () => { - const rawResponse = dsMockUtils.createMockCanTransferResult({ - Ok: dsMockUtils.createMockU8(statusCode), - }); - - dsMockUtils - .createRpcStub('asset', 'canTransfer') - .withArgs(rawAccountId, rawTicker, null, rawToDid, rawAmount) - .returns(rawResponse); - - const result = await transfers.canMint({ to: toDid, amount }); - - expect(result).toBe(TransferStatus.Success); - }); - }); - - describe('method: transfer', () => { - test('should prepare the procedure and return the resulting transaction queue', async () => { - const args = { - to: 'someDid', - amount: new BigNumber(100), - }; - const expectedQueue = ('someQueue' as unknown) as TransactionQueue; - - sinon - .stub(transferToken, 'prepare') - .withArgs({ ticker: mockSecurityToken.ticker, ...args }, mockContext) - .resolves(expectedQueue); - - const queue = await transfers.transfer(args); - - expect(queue).toBe(expectedQueue); - }); - }); }); diff --git a/src/api/procedures/__tests__/issueTokens.ts b/src/api/procedures/__tests__/issueTokens.ts index 7c060d876a..0dc4bc3c2d 100644 --- a/src/api/procedures/__tests__/issueTokens.ts +++ b/src/api/procedures/__tests__/issueTokens.ts @@ -3,12 +3,12 @@ import BigNumber from 'bignumber.js'; import { Ticker } from 'polymesh-types/types'; import sinon from 'sinon'; -import { Identity, SecurityToken } from '~/api/entities'; +import { SecurityToken } from '~/api/entities'; import { getRequiredRoles, Params, prepareIssueTokens } from '~/api/procedures/issueTokens'; import { Context } from '~/base'; import { dsMockUtils, entityMockUtils, procedureMockUtils } from '~/testUtils/mocks'; import { Mocked } from '~/testUtils/types'; -import { RoleType, TransferStatus } from '~/types'; +import { RoleType } from '~/types'; import * as utilsModule from '~/utils'; import { MAX_DECIMALS } from '~/utils/constants'; @@ -133,8 +133,7 @@ describe('issueTokens procedure', () => { }); }); - test('should throw an error if canMint returns a different status from Success', async () => { - const transferStatus = TransferStatus.InvalidSenderIdentity; + test('should throw an error if primary issuance agent is undefined', async () => { const args = { issuanceAmount: { amount, @@ -147,7 +146,6 @@ describe('issueTokens procedure', () => { details: { primaryIssuanceAgent: undefined, }, - transfersCanMint: transferStatus, }, }); @@ -161,10 +159,7 @@ describe('issueTokens procedure', () => { error = err; } - expect(error.message).toBe("You can't issue tokens to primary issuance agent"); - expect(error.data).toMatchObject({ - transferStatus, - }); + expect(error.message).toBe('You should set a primary issuance agent to issue tokens'); }); test('should add a issue transaction to the queue', async () => { diff --git a/src/api/procedures/__tests__/transferToken.ts b/src/api/procedures/__tests__/transferToken.ts deleted file mode 100644 index 3ec95e4dca..0000000000 --- a/src/api/procedures/__tests__/transferToken.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { Balance } from '@polkadot/types/interfaces'; -import BigNumber from 'bignumber.js'; -import { IdentityId, Ticker } from 'polymesh-types/types'; -import sinon from 'sinon'; - -import { SecurityToken } from '~/api/entities'; -import { getRequiredRoles, Params, prepareTransferToken } from '~/api/procedures/transferToken'; -import { Context } from '~/base'; -import { dsMockUtils, entityMockUtils, procedureMockUtils } from '~/testUtils/mocks'; -import { Mocked } from '~/testUtils/types'; -import { RoleType, Signer, TransferStatus } from '~/types'; -import * as utilsModule from '~/utils'; - -jest.mock( - '~/api/entities/SecurityToken', - require('~/testUtils/mocks/entities').mockSecurityTokenModule('~/api/entities/SecurityToken') -); - -describe('transferToken procedure', () => { - let mockContext: Mocked; - let stringToTickerStub: sinon.SinonStub<[string, Context], Ticker>; - let numberToBalanceStub: sinon.SinonStub<[number | BigNumber, Context], Balance>; - let stringToIdentityIdStub: sinon.SinonStub<[string, Context], IdentityId>; - let signerToStringStub: sinon.SinonStub<[string | Signer], string>; - let did: string; - let ticker: string; - let rawTicker: Ticker; - let args: Params; - - beforeAll(() => { - dsMockUtils.initMocks(); - procedureMockUtils.initMocks(); - entityMockUtils.initMocks(); - stringToTickerStub = sinon.stub(utilsModule, 'stringToTicker'); - numberToBalanceStub = sinon.stub(utilsModule, 'numberToBalance'); - stringToIdentityIdStub = sinon.stub(utilsModule, 'stringToIdentityId'); - signerToStringStub = sinon.stub(utilsModule, 'signerToString'); - did = 'someDid'; - ticker = 'TEST'; - rawTicker = dsMockUtils.createMockTicker(ticker); - args = { - to: did, - amount: new BigNumber(100), - ticker, - }; - }); - - beforeEach(() => { - mockContext = dsMockUtils.getContextInstance(); - stringToTickerStub.withArgs(ticker, mockContext).returns(rawTicker); - signerToStringStub.returns('someDid'); - }); - - afterEach(() => { - entityMockUtils.reset(); - procedureMockUtils.reset(); - dsMockUtils.reset(); - }); - - afterAll(() => { - entityMockUtils.cleanup(); - procedureMockUtils.cleanup(); - dsMockUtils.cleanup(); - }); - - test('should throw an error with reason if transfer status is different than success and failure', async () => { - const amount = new BigNumber(100); - const transferStatus = TransferStatus.FundsLimitReached; - - entityMockUtils.configureMocks({ - securityTokenOptions: { - transfersCanTransfer: transferStatus, - }, - }); - - const proc = procedureMockUtils.getInstance(mockContext); - - let error; - - try { - await prepareTransferToken.call(proc, args); - } catch (err) { - error = err; - } - - expect(error.message).toBe( - `You are not allowed to transfer ${amount.toFormat()} "${ticker}" tokens to "${did}"` - ); - expect(error.data).toMatchObject({ transferStatus }); - }); - - test('should throw an error without reason if transfer status is failure', async () => { - const amount = new BigNumber(100); - const transferStatus = TransferStatus.Failure; - - entityMockUtils.configureMocks({ - securityTokenOptions: { - transfersCanTransfer: transferStatus, - }, - }); - - const proc = procedureMockUtils.getInstance(mockContext); - - let error; - - try { - await prepareTransferToken.call(proc, args); - } catch (err) { - error = err; - } - - expect(error.message).toBe( - `You are not allowed to transfer ${amount.toFormat()} "${ticker}" tokens to "${did}"` - ); - expect(error.data).toMatchObject({ transferStatus }); - - return expect(prepareTransferToken.call(proc, { ...args, amount })).rejects.toThrow( - `You are not allowed to transfer ${amount.toFormat()} "${ticker}" tokens to "${did}"` - ); - }); - - test('should add a token transfer transaction to the queue', async () => { - const amount = 100; - const rawAmount = dsMockUtils.createMockBalance(amount); - const rawDid = dsMockUtils.createMockIdentityId(did); - numberToBalanceStub.returns(rawAmount); - stringToIdentityIdStub.returns(rawDid); - - const tx = dsMockUtils.createTxStub('asset', 'transfer'); - const proc = procedureMockUtils.getInstance(mockContext); - - await prepareTransferToken.call(proc, { ...args, amount: new BigNumber(amount) }); - - sinon.assert.calledWith( - procedureMockUtils.getAddTransactionStub(), - tx, - {}, - rawTicker, - rawDid, - rawAmount - ); - }); -}); - -describe('getRequiredRoles', () => { - test('should return a token owner role', () => { - const ticker = 'someTicker'; - const args = { - ticker, - } as Params; - - expect(getRequiredRoles(args)).toEqual([{ type: RoleType.TokenOwner, ticker }]); - }); -}); diff --git a/src/api/procedures/index.ts b/src/api/procedures/index.ts index b82128adc6..68a904340e 100644 --- a/src/api/procedures/index.ts +++ b/src/api/procedures/index.ts @@ -24,7 +24,6 @@ export { setAssetRequirements, SetAssetRequirementsParams } from './setAssetRequ export { toggleFreezeTransfers, ToggleFreezeTransfersParams } from './toggleFreezeTransfers'; export { togglePauseRequirements, TogglePauseRequirementsParams } from './togglePauseRequirements'; export { transferPolyX, TransferPolyXParams } from './transferPolyX'; -export { transferToken, TransferTokenParams } from './transferToken'; export { transferTokenOwnership, TransferTokenOwnershipParams } from './transferTokenOwnership'; // export { voteOnProposal, VoteOnProposalParams } from './voteOnProposal'; export { inviteAccount, InviteAccountParams } from './inviteAccount'; diff --git a/src/api/procedures/issueTokens.ts b/src/api/procedures/issueTokens.ts index 9fd343b43d..518e17c716 100644 --- a/src/api/procedures/issueTokens.ts +++ b/src/api/procedures/issueTokens.ts @@ -1,6 +1,6 @@ import { SecurityToken } from '~/api/entities'; import { PolymeshError, Procedure } from '~/base'; -import { ErrorCode, IssuanceAmount, Role, RoleType, TransferStatus } from '~/types'; +import { ErrorCode, IssuanceAmount, Role, RoleType } from '~/types'; import { numberToBalance, stringToTicker } from '~/utils'; import { MAX_DECIMALS, MAX_TOKEN_AMOUNT } from '~/utils/constants'; @@ -66,19 +66,10 @@ export async function prepareIssueTokens( }); } - let canTransfer = TransferStatus.InvalidSenderIdentity; - - if (primaryIssuanceAgent) { - canTransfer = await securityToken.transfers.canMint({ to: primaryIssuanceAgent, amount }); - } - - if (canTransfer !== TransferStatus.Success) { + if (!primaryIssuanceAgent) { throw new PolymeshError({ code: ErrorCode.ValidationError, - message: "You can't issue tokens to primary issuance agent", - data: { - transferStatus: canTransfer, - }, + message: 'You should set a primary issuance agent to issue tokens', }); } diff --git a/src/api/procedures/transferToken.ts b/src/api/procedures/transferToken.ts deleted file mode 100644 index e79120d1c4..0000000000 --- a/src/api/procedures/transferToken.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { BigNumber } from 'bignumber.js'; - -import { Identity, SecurityToken } from '~/api/entities'; -import { PolymeshError, Procedure } from '~/base'; -import { ErrorCode, Role, RoleType, TransferStatus } from '~/types'; -import { numberToBalance, signerToString, stringToIdentityId, stringToTicker } from '~/utils'; - -export interface TransferTokenParams { - to: string | Identity; - amount: BigNumber; -} - -/** - * @hidden - */ -export type Params = TransferTokenParams & { - ticker: string; -}; - -/** - * @hidden - */ -export async function prepareTransferToken( - this: Procedure, - args: Params -): Promise { - const { - context: { - polymeshApi: { - tx: { asset }, - }, - }, - context, - } = this; - - const { ticker, to, amount } = args; - - const did = signerToString(to); - const value = numberToBalance(amount, context); - const identityId = stringToIdentityId(did, context); - const securityToken = new SecurityToken({ ticker }, context); - - const transferStatus = await securityToken.transfers.canTransfer({ to: did, amount }); - - if (transferStatus !== TransferStatus.Success) { - throw new PolymeshError({ - code: ErrorCode.ValidationError, - message: `You are not allowed to transfer ${amount.toFormat()} "${ticker}" tokens to "${did}"`, - data: { - transferStatus, - }, - }); - } - - const rawTicker = stringToTicker(ticker, context); - - this.addTransaction(asset.transfer, {}, rawTicker, identityId, value); - - return securityToken; -} - -/** - * @hidden - */ -export function getRequiredRoles({ ticker }: Params): Role[] { - return [{ type: RoleType.TokenOwner, ticker }]; -} - -/** - * @hidden - */ -export const transferToken = new Procedure(prepareTransferToken, getRequiredRoles); diff --git a/src/middleware/types.ts b/src/middleware/types.ts index b77d041bdc..28d30aa508 100644 --- a/src/middleware/types.ts +++ b/src/middleware/types.ts @@ -492,7 +492,6 @@ export enum EventIdEnum { AssetCreated = 'AssetCreated', IdentifiersUpdated = 'IdentifiersUpdated', DivisibilityChanged = 'DivisibilityChanged', - TransferWithData = 'TransferWithData', IsIssuable = 'IsIssuable', CustodyTransfer = 'CustodyTransfer', CustodyAllowanceChanged = 'CustodyAllowanceChanged', @@ -758,15 +757,12 @@ export enum CallIdEnum { RenameAsset = 'rename_asset', ControllerTransfer = 'controller_transfer', Approve = 'approve', - TransferFrom = 'transfer_from', CreateCheckpoint = 'create_checkpoint', Issue = 'issue', Redeem = 'redeem', RedeemFrom = 'redeem_from', ControllerRedeem = 'controller_redeem', MakeDivisible = 'make_divisible', - TransferWithData = 'transfer_with_data', - TransferFromWithData = 'transfer_from_with_data', IsIssuable = 'is_issuable', BatchAddDocument = 'batch_add_document', BatchRemoveDocument = 'batch_remove_document', diff --git a/src/polkadot/polymesh/definitions.ts b/src/polkadot/polymesh/definitions.ts index 8dbfbfb342..a3f3b3815c 100644 --- a/src/polkadot/polymesh/definitions.ts +++ b/src/polkadot/polymesh/definitions.ts @@ -1202,8 +1202,7 @@ export default { }, asset: { canTransfer: { - description: - 'Checks whether a transaction with ' + 'given parameters can take place or ' + 'not', + description: 'Checks whether a transaction with given parameters can take place or not', params: [ { name: 'sender', @@ -1211,20 +1210,30 @@ export default { isOptional: false, }, { - name: 'ticker', - type: 'Ticker', + name: 'from_custodian', + type: 'Option', isOptional: false, }, { - name: 'from_did', - type: 'Option', + name: 'from_portfolio', + type: 'PortfolioId', isOptional: false, }, { - name: 'to_did', + name: 'to_custodian', type: 'Option', isOptional: false, }, + { + name: 'to_portfolio', + type: 'PortfolioId', + isOptional: false, + }, + { + name: 'ticker', + type: 'Ticker', + isOptional: false, + }, { name: 'value', type: 'Balance', diff --git a/src/polkadot/types.ts b/src/polkadot/types.ts index b2c46b7df6..95d2a1d660 100644 --- a/src/polkadot/types.ts +++ b/src/polkadot/types.ts @@ -217,17 +217,14 @@ export enum AssetTx { Freeze = 'asset.freeze', Unfreeze = 'asset.unfreeze', RenameAsset = 'asset.renameAsset', - Transfer = 'asset.transfer', ControllerTransfer = 'asset.controllerTransfer', Approve = 'asset.approve', - TransferFrom = 'asset.transferFrom', CreateCheckpoint = 'asset.createCheckpoint', Issue = 'asset.issue', Redeem = 'asset.redeem', RedeemFrom = 'asset.redeemFrom', ControllerRedeem = 'asset.controllerRedeem', MakeDivisible = 'asset.makeDivisible', - TransferWithData = 'asset.transferWithData', TransferFromWithData = 'asset.transferFromWithData', IsIssuable = 'asset.isIssuable', BatchAddDocument = 'asset.batchAddDocument', diff --git a/src/types/index.ts b/src/types/index.ts index e3d0749662..6835b7f7c3 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,7 +1,7 @@ import { Keyring } from '@polkadot/api'; import { IKeyringPair, TypeDef } from '@polkadot/types/types'; import BigNumber from 'bignumber.js'; -import { TxTag } from 'polymesh-types/types'; +import { IdentityId, TxTag } from 'polymesh-types/types'; // NOTE uncomment in Governance v2 upgrade import { Account, Identity /*, Proposal */ } from '~/api/entities'; @@ -133,6 +133,12 @@ export enum TokenIdentifierType { Dti = 'Dti', } +export enum KnownPortfolioKind { + Default = 'Default', +} + +export type PortfolioKind = KnownPortfolioKind | { user: number }; + // NOTE: query.asset.identifiers doesn’t support custom identifier types properly for now // export type TokenIdentifierType = KnownTokenIdentifierType | { custom: string }; @@ -477,6 +483,11 @@ export interface SecondaryKey { permissions: Permission[]; } +export interface PortfolioId { + did: IdentityId; + kind: PortfolioKind; +} + export { TxTags } from 'polymesh-types/types'; export { Signer as PolkadotSigner } from '@polkadot/api/types'; export * from '~/api/entities/types'; diff --git a/src/utils/__tests__/index.ts b/src/utils/__tests__/index.ts index 1a19247898..22eb1c6355 100644 --- a/src/utils/__tests__/index.ts +++ b/src/utils/__tests__/index.ts @@ -3,7 +3,7 @@ import { AccountId, Balance, Moment } from '@polkadot/types/interfaces'; import { ISubmittableResult } from '@polkadot/types/types'; import BigNumber from 'bignumber.js'; import { range } from 'lodash'; -import { ComplianceRequirement, Memo, PipId } from 'polymesh-types/polymesh'; +import { ComplianceRequirement, Memo, PipId, PortfolioId } from 'polymesh-types/polymesh'; import { AssetIdentifier, AssetName, @@ -19,6 +19,7 @@ import { IdentifierType, IdentityId, Permission as MeshPermission, + PortfolioKind as MeshPortfolioKind, ProtocolOp, Signatory, Ticker, @@ -40,6 +41,7 @@ import { ConditionTarget, ConditionType, CountryCode, + KnownPortfolioKind, KnownTokenType, Permission, Signer, @@ -97,6 +99,8 @@ import { numberToU64, padString, permissionToMeshPermission, + portfolioIdToMeshPortfolioId, + portfolioKindToMeshPortfolioKind, posRatioToBigNumber, removePadding, requestAtBlock, @@ -283,6 +287,67 @@ describe('stringToIdentityId and identityIdToString', () => { }); }); +describe('portfolioKindToMeshPortfolioKind', () => { + beforeAll(() => { + dsMockUtils.initMocks(); + }); + + afterEach(() => { + dsMockUtils.reset(); + }); + + afterAll(() => { + dsMockUtils.cleanup(); + }); + + test('portfolioKindToMeshPortfolioKind should convert a portfolio kind object into a polkadot portfolio kind', () => { + const portfolioKind = KnownPortfolioKind.Default; + const fakeResult = ('PortfolioKind' as unknown) as MeshPortfolioKind; + const context = dsMockUtils.getContextInstance(); + + dsMockUtils + .getCreateTypeStub() + .withArgs('PortfolioKind', portfolioKind) + .returns(fakeResult); + + const result = portfolioKindToMeshPortfolioKind(portfolioKind, context); + + expect(result).toBe(fakeResult); + }); +}); + +describe('portfolioIdToMeshPortfolioId', () => { + beforeAll(() => { + dsMockUtils.initMocks(); + }); + + afterEach(() => { + dsMockUtils.reset(); + }); + + afterAll(() => { + dsMockUtils.cleanup(); + }); + + test('portfolioIdToMeshPortfolioId should convert a portfolio id into a polkadot portfolio id', () => { + const portfolioId = { + did: dsMockUtils.createMockIdentityId(), + kind: KnownPortfolioKind.Default, + }; + const fakeResult = ('PortfolioId' as unknown) as PortfolioId; + const context = dsMockUtils.getContextInstance(); + + dsMockUtils + .getCreateTypeStub() + .withArgs('PortfolioId', portfolioId) + .returns(fakeResult); + + const result = portfolioIdToMeshPortfolioId(portfolioId, context); + + expect(result).toBe(fakeResult); + }); +}); + describe('signerToString', () => { test('signerToString should return the Indentity DID string', () => { const did = 'someDid'; diff --git a/src/utils/index.ts b/src/utils/index.ts index d3c06e37b4..fa264aee2f 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -36,6 +36,8 @@ import { IdentifierType, IdentityId, Permission as MeshPermission, + PortfolioId as MeshPortfolioId, + PortfolioKind as MeshPortfolioKind, PosRatio, ProposalState as MeshProposalState, ProtocolOp, @@ -74,6 +76,8 @@ import { NextKey, PaginationOptions, Permission, + PortfolioId, + PortfolioKind, Requirement, RequirementCompliance, SecondaryKey, @@ -270,6 +274,26 @@ export function identityIdToString(identityId: IdentityId): string { return identityId.toString(); } +/** + * @hidden + */ +export function portfolioKindToMeshPortfolioKind( + portfolioKind: PortfolioKind, + context: Context +): MeshPortfolioKind { + return context.polymeshApi.createType('PortfolioKind', portfolioKind); +} + +/** + * @hidden + */ +export function portfolioIdToMeshPortfolioId( + portfolioId: PortfolioId, + context: Context +): MeshPortfolioId { + return context.polymeshApi.createType('PortfolioId', portfolioId); +} + /** * @hidden */