Skip to content

Commit

Permalink
feat: adapt canTransfer to portfolio logic. MSDK-292
Browse files Browse the repository at this point in the history
  • Loading branch information
shuffledex committed Sep 28, 2020
1 parent a6ec93f commit 4a2e3b2
Show file tree
Hide file tree
Showing 13 changed files with 137 additions and 333 deletions.
43 changes: 11 additions & 32 deletions src/api/entities/SecurityToken/Transfers.ts
Expand Up @@ -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,
Expand Down Expand Up @@ -76,7 +77,7 @@ export class Transfers extends Namespace<SecurityToken> {
}

/**
* 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
Expand All @@ -91,21 +92,11 @@ export class Transfers extends Namespace<SecurityToken> {
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<TransferStatus> {
return this._canTransfer({ ...args, from: null });
}

/**
* @hidden
*/
private async _canTransfer(args: {
from?: null | string | Identity;
from: string | Identity;
to: string | Identity;
amount: BigNumber;
}): Promise<TransferStatus> {
Expand All @@ -119,11 +110,8 @@ export class Transfers extends Namespace<SecurityToken> {

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
Expand All @@ -134,23 +122,14 @@ export class Transfers extends Namespace<SecurityToken> {
// 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<TransactionQueue<SecurityToken>> {
const {
parent: { ticker },
context,
} = this;
return transferToken.prepare({ ticker, ...args }, context);
}
}
38 changes: 1 addition & 37 deletions src/api/entities/SecurityToken/__tests__/Transfers.ts
Expand Up @@ -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';
Expand Down Expand Up @@ -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<SecurityToken>;

sinon
.stub(transferToken, 'prepare')
.withArgs({ ticker: mockSecurityToken.ticker, ...args }, mockContext)
.resolves(expectedQueue);

const queue = await transfers.transfer(args);

expect(queue).toBe(expectedQueue);
});
});
});
13 changes: 4 additions & 9 deletions src/api/procedures/__tests__/issueTokens.ts
Expand Up @@ -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';

Expand Down Expand Up @@ -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,
Expand All @@ -147,7 +146,6 @@ describe('issueTokens procedure', () => {
details: {
primaryIssuanceAgent: undefined,
},
transfersCanMint: transferStatus,
},
});

Expand All @@ -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 () => {
Expand Down
154 changes: 0 additions & 154 deletions src/api/procedures/__tests__/transferToken.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/api/procedures/index.ts
Expand Up @@ -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';
15 changes: 3 additions & 12 deletions 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';

Expand Down Expand Up @@ -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',
});
}

Expand Down

0 comments on commit 4a2e3b2

Please sign in to comment.