Skip to content

Commit

Permalink
feat: add documents to token creation
Browse files Browse the repository at this point in the history
Also fixed bugs in number to balance conversion and added did to ST (will be needed when fetching
documents)
  • Loading branch information
monitz87 committed Mar 17, 2020
1 parent 96a0d72 commit 7f17e0a
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
Expand Up @@ -2,7 +2,7 @@ import { Balance } from '@polkadot/types/interfaces';

import { Entity } from '~/base';
import { polkadotMockUtils } from '~/testUtils/mocks';
import { balanceToBigNumber } from '~/utils';
import { balanceToBigNumber, tickerToDid } from '~/utils';

import { SecurityToken } from '../';

Expand All @@ -24,12 +24,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
@@ -1,7 +1,13 @@
import { Identity } from '~/api/entities/Identity';
import { Entity } 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 @@ -29,6 +35,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 @@ -43,6 +54,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
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
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
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

0 comments on commit 7f17e0a

Please sign in to comment.