Skip to content

Commit

Permalink
Merge pull request #39 from PolymathNetwork/feat/MSDK-40-add-document…
Browse files Browse the repository at this point in the history
…s-st-creation

Feat/msdk 40 add documents st creation
  • Loading branch information
VictorVicente authored Mar 18, 2020
2 parents 1bef876 + 970ea99 commit a4e35d8
Show file tree
Hide file tree
Showing 7 changed files with 416 additions and 15 deletions.
5 changes: 3 additions & 2 deletions src/api/entities/SecurityToken/__tests__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import sinon from 'sinon';
import { modifyToken } from '~/api/procedures';
import { Entity, TransactionQueue } from '~/base';
import { polkadotMockUtils } from '~/testUtils/mocks';
import { balanceToBigNumber } from '~/utils';
import { balanceToBigNumber, tickerToDid } from '~/utils';

import { SecurityToken } from '../';

Expand All @@ -26,12 +26,13 @@ describe('SecurityToken class', () => {
});

describe('constructor', () => {
test('should assign ticker to instance', () => {
test('should assign ticker and did to instance', () => {
const ticker = 'test';
const context = polkadotMockUtils.getContextInstance();
const securityToken = new SecurityToken({ ticker }, context);

expect(securityToken.ticker).toBe(ticker);
expect(securityToken.did).toBe(tickerToDid(ticker));
});
});

Expand Down
14 changes: 13 additions & 1 deletion src/api/entities/SecurityToken/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import { Identity } from '~/api/entities/Identity';
import { modifyToken, ModifyTokenParams } from '~/api/procedures';
import { Entity, TransactionQueue } from '~/base';
import { Context } from '~/context';
import { balanceToBigNumber, boolToBoolean, identityIdToString, tokenNameToString } from '~/utils';
import {
balanceToBigNumber,
boolToBoolean,
identityIdToString,
tickerToDid,
tokenNameToString,
} from '~/utils';

import { SecurityTokenDetails } from './types';

Expand Down Expand Up @@ -30,6 +36,11 @@ export class SecurityToken extends Entity<UniqueIdentifiers> {
return typeof ticker === 'string';
}

/**
* identity id of the Security Token
*/
public did: string;

/**
* ticker of the Security Token
*/
Expand All @@ -44,6 +55,7 @@ export class SecurityToken extends Entity<UniqueIdentifiers> {
const { ticker } = identifiers;

this.ticker = ticker;
this.did = tickerToDid(ticker);
}

/**
Expand Down
46 changes: 42 additions & 4 deletions src/api/procedures/__tests__/createSecurityToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import BigNumber from 'bignumber.js';
import {
AssetIdentifier,
AssetType,
Document,
FundingRoundName,
IdentifierType,
Ticker,
Expand All @@ -21,6 +22,7 @@ import {
KnownTokenIdentifierType,
KnownTokenType,
TickerReservationStatus,
TokenDocument,
TokenIdentifier,
TokenIdentifierType,
TokenType,
Expand Down Expand Up @@ -48,20 +50,23 @@ describe('createSecurityToken procedure', () => {
>;
let stringToAssetIdentifierStub: sinon.SinonStub<[string, Context], AssetIdentifier>;
let stringToFundingRoundNameStub: sinon.SinonStub<[string, Context], FundingRoundName>;
let tokenDocumentToDocumentStub: sinon.SinonStub<[TokenDocument, Context], Document>;
let ticker: string;
let name: string;
let totalSupply: BigNumber;
let isDivisible: boolean;
let tokenType: TokenType;
let tokenIdentifiers: TokenIdentifier[];
let fundingRound: string;
let documents: TokenDocument[];
let rawTicker: Ticker;
let rawName: TokenName;
let rawTotalSupply: Balance;
let rawIsDivisible: bool;
let rawType: AssetType;
let rawIdentifiers: [IdentifierType, AssetIdentifier][];
let rawFundingRound: FundingRoundName;
let rawDocuments: Document[];
let args: Params;
let fee: number;

Expand All @@ -80,6 +85,7 @@ describe('createSecurityToken procedure', () => {
);
stringToAssetIdentifierStub = sinon.stub(utilsModule, 'stringToAssetIdentifier');
stringToFundingRoundNameStub = sinon.stub(utilsModule, 'stringToFundingRoundName');
tokenDocumentToDocumentStub = sinon.stub(utilsModule, 'tokenDocumentToDocument');
ticker = 'someTicker';
name = 'someName';
totalSupply = new BigNumber(100);
Expand All @@ -92,6 +98,13 @@ describe('createSecurityToken procedure', () => {
},
];
fundingRound = 'Series A';
documents = [
{
name: 'someDocument',
uri: 'someUri',
contentHash: 'someHash',
},
];
rawTicker = polkadotMockUtils.createMockTicker(ticker);
rawName = polkadotMockUtils.createMockTokenName(name);
rawTotalSupply = polkadotMockUtils.createMockBalance(totalSupply.toNumber());
Expand All @@ -103,6 +116,14 @@ describe('createSecurityToken procedure', () => {
polkadotMockUtils.createMockAssetIdentifier(value),
];
});
rawDocuments = documents.map(({ name, uri, contentHash }) =>
polkadotMockUtils.createMockDocument({
name: polkadotMockUtils.createMockDocumentName(name),
uri: polkadotMockUtils.createMockDocumentUri(uri),
// eslint-disable-next-line @typescript-eslint/camelcase
content_hash: polkadotMockUtils.createMockDocumentHash(contentHash),
})
);
rawFundingRound = polkadotMockUtils.createMockFundingRoundName(fundingRound);
args = {
ticker,
Expand Down Expand Up @@ -171,6 +192,7 @@ describe('createSecurityToken procedure', () => {
.withArgs(tokenIdentifiers[0].value, mockContext)
.returns(rawIdentifiers[0][1]);
stringToFundingRoundNameStub.withArgs(fundingRound, mockContext).returns(rawFundingRound);
tokenDocumentToDocumentStub.withArgs(documents[0], mockContext).returns(rawDocuments[0]);
});

afterEach(() => {
Expand Down Expand Up @@ -249,7 +271,7 @@ describe('createSecurityToken procedure', () => {
const result = await prepareCreateSecurityToken.call(proc, args);

sinon.assert.calledWith(
addTransactionStub,
addTransactionStub.firstCall,
transaction,
sinon.match({
fee: new BigNumber(fee),
Expand All @@ -264,10 +286,14 @@ describe('createSecurityToken procedure', () => {
);
expect(result).toMatchObject(new SecurityToken({ ticker }, mockContext));

await prepareCreateSecurityToken.call(proc, { ...args, fundingRound: undefined });
await prepareCreateSecurityToken.call(proc, {
...args,
tokenIdentifiers: undefined,
fundingRound: undefined,
});

sinon.assert.calledWith(
addTransactionStub,
addTransactionStub.secondCall,
transaction,
sinon.match({
fee: new BigNumber(fee),
Expand All @@ -277,8 +303,20 @@ describe('createSecurityToken procedure', () => {
rawTotalSupply,
rawIsDivisible,
rawType,
rawIdentifiers,
[],
null
);
});

test('should add a document add transaction to the queue', async () => {
const proc = procedureMockUtils.getInstance<Params, SecurityToken>();
proc.context = mockContext;
const tx = polkadotMockUtils.createTxStub('asset', 'addDocuments');

const result = await prepareCreateSecurityToken.call(proc, { ...args, documents });

sinon.assert.calledWith(addTransactionStub, tx, {}, rawTicker, rawDocuments);

expect(result).toMatchObject(new SecurityToken({ ticker }, mockContext));
});
});
21 changes: 18 additions & 3 deletions src/api/procedures/createSecurityToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import { AssetIdentifier, IdentifierType } from 'polymesh-types/types';

import { SecurityToken, TickerReservation } from '~/api/entities';
import { PolymeshError, Procedure } from '~/base';
import { ErrorCode, TickerReservationStatus, TokenIdentifier, TokenType } from '~/types';
import {
ErrorCode,
TickerReservationStatus,
TokenDocument,
TokenIdentifier,
TokenType,
} from '~/types';
import {
balanceToBigNumber,
booleanToBool,
Expand All @@ -12,6 +18,7 @@ import {
stringToFundingRoundName,
stringToTicker,
stringToTokenName,
tokenDocumentToDocument,
tokenIdentifierTypeToIdentifierType,
tokenTypeToAssetType,
} from '~/utils';
Expand All @@ -21,8 +28,9 @@ export interface CreateSecurityTokenParams {
totalSupply: BigNumber;
isDivisible: boolean;
tokenType: TokenType;
tokenIdentifiers: TokenIdentifier[];
tokenIdentifiers?: TokenIdentifier[];
fundingRound?: string;
documents?: TokenDocument[];
}

export type Params = CreateSecurityTokenParams & {
Expand All @@ -48,8 +56,9 @@ export async function prepareCreateSecurityToken(
totalSupply,
isDivisible,
tokenType,
tokenIdentifiers,
tokenIdentifiers = [],
fundingRound,
documents,
} = args;

const reservation = new TickerReservation({ ticker }, context);
Expand Down Expand Up @@ -120,6 +129,12 @@ export async function prepareCreateSecurityToken(
rawFundingRound
);

if (documents) {
const rawDocuments = documents.map(document => tokenDocumentToDocument(document, context));

this.addTransaction(tx.asset.addDocuments, {}, rawTicker, rawDocuments);
}

return new SecurityToken({ ticker }, context);
}

Expand Down
15 changes: 15 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ export enum KnownTokenType {
StructuredProduct = 'structuredProduct',
}

/**
* Type of security that the token represents
*/
export type TokenType = KnownTokenType | { custom: string };

export enum KnownTokenIdentifierType {
Expand All @@ -72,11 +75,23 @@ export enum KnownTokenIdentifierType {

export type TokenIdentifierType = KnownTokenIdentifierType | { custom: string };

/**
* Alphanumeric standardized security identifier
*/
export interface TokenIdentifier {
type: TokenIdentifierType;
value: string;
}

/**
* Document attached to a token
*/
export interface TokenDocument {
name: string;
uri: string;
contentHash: string;
}

/**
* Specifies possible types of errors in the SDK
*/
Expand Down
Loading

0 comments on commit a4e35d8

Please sign in to comment.