Skip to content

Commit

Permalink
fix: feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
shuffledex committed Apr 15, 2020
1 parent 9ad5b06 commit 02238ed
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 102 deletions.
23 changes: 23 additions & 0 deletions src/api/entities/SecurityToken/Issuance.ts
@@ -0,0 +1,23 @@
import { issueTokens } from '~/api/procedures';
import { Namespace, TransactionQueue } from '~/base';
import { IssuanceData } from '~/types';

import { SecurityToken } from '.';

/**
* Handles all Security Token Issuance related functionality
*/
export class Issuance extends Namespace<SecurityToken> {
/**
* Issue a certain amount of tokens to one or multiple identities. The receiving identities must comply with any receiver rules set on the token
*
* @param args.issuanceData - array that specifies who to issue tokens to and which amounts
*/
public issue(args: { issuanceData: IssuanceData[] }): Promise<TransactionQueue<SecurityToken>> {
const {
parent: { ticker },
context,
} = this;
return issueTokens.prepare({ ticker, ...args }, context);
}
}
23 changes: 0 additions & 23 deletions src/api/entities/SecurityToken/Issuances.ts

This file was deleted.

Expand Up @@ -2,28 +2,30 @@ import BigNumber from 'bignumber.js';
import sinon from 'sinon';

import { SecurityToken } from '~/api/entities';
import { setIssuancesData } from '~/api/procedures';
import { issueTokens } from '~/api/procedures';
import { Namespace, TransactionQueue } from '~/base';
import { entityMockUtils, polkadotMockUtils } from '~/testUtils/mocks';

import { Issuances } from '../Issuances';
import { Issuance } from '../Issuance';

describe('Issuances class', () => {
describe('Issuance class', () => {
beforeAll(() => {
entityMockUtils.initMocks();
polkadotMockUtils.initMocks();
});

afterEach(() => {
entityMockUtils.reset();
polkadotMockUtils.reset();
});

afterAll(() => {
entityMockUtils.cleanup();
polkadotMockUtils.cleanup();
});

test('should extend namespace', () => {
expect(Issuances.prototype instanceof Namespace).toBe(true);
expect(Issuance.prototype instanceof Namespace).toBe(true);
});

describe('method: issue', () => {
Expand All @@ -34,25 +36,25 @@ describe('Issuances class', () => {
test('should prepare the procedure with the correct arguments and context, and return the resulting transaction queue', async () => {
const context = polkadotMockUtils.getContextInstance();
const token = entityMockUtils.getSecurityTokenInstance();
const issuances = new Issuances(token, context);
const issuance = new Issuance(token, context);

const args = {
issuances: [
issuanceData: [
{
did: 'someDid',
balance: new BigNumber(100),
amount: new BigNumber(100),
},
],
};

const expectedQueue = ('someQueue' as unknown) as TransactionQueue<SecurityToken>;

sinon
.stub(setIssuancesData, 'prepare')
.stub(issueTokens, 'prepare')
.withArgs({ ticker: token.ticker, ...args }, context)
.resolves(expectedQueue);

const queue = await issuances.issue(args);
const queue = await issuance.issue(args);

expect(queue).toBe(expectedQueue);
});
Expand Down
6 changes: 3 additions & 3 deletions src/api/entities/SecurityToken/index.ts
Expand Up @@ -23,7 +23,7 @@ import {
} from '~/utils';

import { Documents } from './Documents';
import { Issuances } from './Issuances';
import { Issuance } from './Issuance';
import { Transfers } from './Transfers';
import { SecurityTokenDetails } from './types';

Expand Down Expand Up @@ -64,7 +64,7 @@ export class SecurityToken extends Entity<UniqueIdentifiers> {
// Namespaces
public documents: Documents;
public transfers: Transfers;
public issuances: Issuances;
public issuance: Issuance;

/**
* @hidden
Expand All @@ -79,7 +79,7 @@ export class SecurityToken extends Entity<UniqueIdentifiers> {

this.documents = new Documents(this, context);
this.transfers = new Transfers(this, context);
this.issuances = new Issuances(this, context);
this.issuance = new Issuance(this, context);
}

/**
Expand Down
@@ -1,25 +1,23 @@
import { Balance } from '@polkadot/types/interfaces';
import BigNumber from 'bignumber.js';
import sinon from 'sinon';

import { SecurityToken } from '~/api/entities';
import {
getRequiredRoles,
Params,
prepareSetIssuancesData,
} from '~/api/procedures/setIssuancesData';
import { getRequiredRoles, Params, prepareIssueTokens } from '~/api/procedures/issueTokens';
import { Context } from '~/context';
import { Ticker } from '~/polkadot';
import { IdentityId, Ticker } from '~/polkadot';
import { entityMockUtils, polkadotMockUtils, procedureMockUtils } from '~/testUtils/mocks';
import { Mocked } from '~/testUtils/types';
import { RoleType } from '~/types';
import * as utilsModule from '~/utils';
import { MAX_DECIMALS, MAX_TOKEN_AMOUNT } from '~/utils/constants';

jest.mock(
'~/api/entities/SecurityToken',
require('~/testUtils/mocks/entities').mockSecurityTokenModule('~/api/entities/SecurityToken')
);

describe('setIssuancesData procedure', () => {
describe('issueTokens procedure', () => {
let mockContext: Mocked<Context>;
let stringToTickerStub: sinon.SinonStub<[string, Context], Ticker>;
let ticker: string;
Expand Down Expand Up @@ -53,16 +51,16 @@ describe('setIssuancesData procedure', () => {
polkadotMockUtils.cleanup();
});

test('should throw an error if security token is divisible and at least one balance exceeds six decimals', () => {
test('should throw an error if security token is divisible and at least one amount exceeds six decimals', () => {
const args = {
issuances: [
issuanceData: [
{
did: 'someDid',
balance: new BigNumber(100),
amount: new BigNumber(100),
},
{
did: 'anotherDid',
balance: new BigNumber(50.1234567),
amount: new BigNumber(50.1234567),
},
],
ticker,
Expand All @@ -79,21 +77,21 @@ describe('setIssuancesData procedure', () => {
const proc = procedureMockUtils.getInstance<Params, SecurityToken>();
proc.context = mockContext;

return expect(prepareSetIssuancesData.call(proc, args)).rejects.toThrow(
'At most one balance exceeds the six decimals limit'
return expect(prepareIssueTokens.call(proc, args)).rejects.toThrow(
`Issuance amounts cannot have more than ${MAX_DECIMALS} decimals`
);
});

test('should throw an error if security token is not divisible and at least one balance has decimals', () => {
test('should throw an error if security token is not divisible and at least one amount has decimals', () => {
const args = {
issuances: [
issuanceData: [
{
did: 'someDid',
balance: new BigNumber(100),
amount: new BigNumber(100),
},
{
did: 'anotherDid',
balance: new BigNumber(50.1),
amount: new BigNumber(50.1),
},
],
ticker,
Expand All @@ -102,17 +100,17 @@ describe('setIssuancesData procedure', () => {
const proc = procedureMockUtils.getInstance<Params, SecurityToken>();
proc.context = mockContext;

return expect(prepareSetIssuancesData.call(proc, args)).rejects.toThrow(
'At most one balance has decimals'
return expect(prepareIssueTokens.call(proc, args)).rejects.toThrow(
'Cannot issue decimal amounts of an indivisible token'
);
});

test('should throw an error if token supply is bigger than the limit total supply', () => {
const args = {
issuances: [
issuanceData: [
{
did: 'someDid',
balance: new BigNumber(100),
amount: new BigNumber(100),
},
],
ticker,
Expand All @@ -131,53 +129,48 @@ describe('setIssuancesData procedure', () => {
const proc = procedureMockUtils.getInstance<Params, SecurityToken>();
proc.context = mockContext;

return expect(prepareSetIssuancesData.call(proc, args)).rejects.toThrow(
`The total supply for "${ticker}" cannot be bigger than ${limitTotalSupply.toString()}`
return expect(prepareIssueTokens.call(proc, args)).rejects.toThrow(
`This issuance operation will cause the total supply of "${ticker}" to exceed the maximum allowed (${MAX_TOKEN_AMOUNT.toFormat()})`
);
});

test('should add a batch issue transaction to the queue', async () => {
const balanceOne = 100;
const balanceTwo = 200;
const args = {
issuances: [
issuanceData: [
{
did: 'someDid',
balance: new BigNumber(balanceOne),
amount: new BigNumber(100),
},
{
did: 'otherDid',
balance: new BigNumber(balanceTwo),
amount: new BigNumber(200),
},
],
ticker,
};

const someIdentityId = 'someIdentityId';
const otherIdentityId = 'otherIdentityId';

const investors = [
polkadotMockUtils.createMockIdentityId(someIdentityId),
polkadotMockUtils.createMockIdentityId(otherIdentityId),
];
const balances = [
polkadotMockUtils.createMockBalance(balanceOne),
polkadotMockUtils.createMockBalance(balanceTwo),
];
const investors: IdentityId[] = [];
const balances: Balance[] = [];

const stringToIdentityIdStub = sinon.stub(utilsModule, 'stringToIdentityId');
const numberToBalanceStub = sinon.stub(utilsModule, 'numberToBalance');

stringToIdentityIdStub.withArgs(args.issuances[0].did, mockContext).returns(investors[0]);
stringToIdentityIdStub.withArgs(args.issuances[1].did, mockContext).returns(investors[1]);
numberToBalanceStub.withArgs(args.issuances[0].balance, mockContext).returns(balances[0]);
numberToBalanceStub.withArgs(args.issuances[1].balance, mockContext).returns(balances[1]);
args.issuanceData.forEach(data => {
const identityId = polkadotMockUtils.createMockIdentityId(`${data.did}Identity`);
const balance = polkadotMockUtils.createMockBalance(data.amount.toNumber());

investors.push(identityId);
balances.push(balance);

stringToIdentityIdStub.withArgs(data.did, mockContext).returns(identityId);
numberToBalanceStub.withArgs(data.amount, mockContext).returns(balance);
});

const transaction = polkadotMockUtils.createTxStub('asset', 'batchIssue');
const proc = procedureMockUtils.getInstance<Params, SecurityToken>();
proc.context = mockContext;

const result = await prepareSetIssuancesData.call(proc, args);
const result = await prepareIssueTokens.call(proc, args);

sinon.assert.calledWith(addTransactionStub, transaction, {}, rawTicker, investors, balances);
expect(result.ticker).toBe(ticker);
Expand Down
2 changes: 1 addition & 1 deletion src/api/procedures/index.ts
Expand Up @@ -5,4 +5,4 @@ export { createSecurityToken, CreateSecurityTokenParams } from './createSecurity
export { setTokenDocuments, SetTokenDocumentsParams } from './setTokenDocuments';
export { transferTokenOwnership, TransferTokenOwnershipParams } from './transferTokenOwnership';
export { consumeAuthorizationRequests, ConsumeParams } from './consumeAuthorizationRequests';
export { setIssuancesData, SetIssuancesDataParams } from './setIssuancesData';
export { issueTokens, IssueTokensParams } from './issueTokens';

0 comments on commit 02238ed

Please sign in to comment.