Skip to content

Commit

Permalink
Merge branch 'beta' into feat/transfer-ticker-ownership
Browse files Browse the repository at this point in the history
  • Loading branch information
shuffledex committed Dec 23, 2019
2 parents af1e80a + 127ee9b commit 64aa648
Show file tree
Hide file tree
Showing 9 changed files with 638 additions and 8 deletions.
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "@polymathnetwork/sdk",
"version": "2.0.1-beta.82",
"version": "2.0.1-beta.83",
"description": "A Javascript SDK for interacting with the Polymath network for the browser and Node.js",
"bugs": {
"url": "https://github.com/PolymathNetwork/polymath-sdk/issues"
Expand Down
93 changes: 92 additions & 1 deletion src/entities/SecurityToken/Documents.ts
@@ -1,3 +1,94 @@
import { SubModule } from './SubModule';
import { PolymathError } from '../../PolymathError';
import { ErrorCode } from '../../types';
import { SetDocument } from '../../procedures/SetDocument';
import { RemoveDocument } from '../../procedures/RemoveDocument';

export class Documents extends SubModule {}
interface Document {
name: string;
documentUri: string;
documentHash: string;
updatedAt: Date;
}

export class Documents extends SubModule {
/**
* Attach a new document to the contract, or update the URI or hash of an existing attached document
* @param name Name of the document. It should be unique always
* @param uri Off-chain uri of the document from where it is accessible to investors/advisors to read.
* @param documentHash hash (of the contents) of the document.
*/
public async set(args: { name: string; uri: string; documentHash: string }) {
const { symbol } = this.securityToken;

const procedure = new SetDocument({ symbol, ...args }, this.context);

return procedure.prepare();
}

/**
* Remove an existing document from the contract giving the name of the document.
* @param name Name of the document. It should be unique always
*/
public async remove(args: { name: string }) {
const { symbol } = this.securityToken;

const procedure = new RemoveDocument({ symbol, ...args }, this.context);

return procedure.prepare();
}

/**
* Retrieve a specific document's data by name
* @param name Unique name of the document
*/
public getDocument = async (args: { name: string }): Promise<Document> => {
const {
context: { contractWrappers },
securityToken,
} = this;

const { symbol } = securityToken;
let securityTokenInstance;

try {
securityTokenInstance = await contractWrappers.tokenFactory.getSecurityTokenInstanceFromTicker(
symbol
);
} catch (err) {
throw new PolymathError({
code: ErrorCode.FetcherValidationError,
message: `There is no Security Token with symbol ${symbol}`,
});
}

const { documentTime: updatedAt, ...info } = await securityTokenInstance.getDocument(args);
return { updatedAt, ...args, ...info };
};

/**
* Retrieve an array of all the documents attached to the security token
*/
public getAllDocuments = async (): Promise<Document[]> => {
const {
context: { contractWrappers },
securityToken,
} = this;

const { symbol } = securityToken;
let securityTokenInstance;

try {
securityTokenInstance = await contractWrappers.tokenFactory.getSecurityTokenInstanceFromTicker(
symbol
);
} catch (err) {
throw new PolymathError({
code: ErrorCode.FetcherValidationError,
message: `There is no Security Token with symbol ${symbol}`,
});
}
const documentList = await securityTokenInstance.getAllDocuments();
return Promise.all(documentList.map(docname => this.getDocument({ name: docname })));
};
}
55 changes: 49 additions & 6 deletions src/entities/SecurityToken/Shareholders.ts
Expand Up @@ -3,12 +3,7 @@ import {
SecurityToken as SecurityTokenWrapper,
} from '@polymathnetwork/contract-wrappers';
import { ShareholderDataEntry, ErrorCode } from '../../types';
import {
ModifyShareholderData,
CreateCheckpoint,
RevokeKyc,
FreezeIssuance,
} from '../../procedures';
import { ModifyShareholderData, CreateCheckpoint, RevokeKyc } from '../../procedures';
import { SubModule } from './SubModule';
import { Checkpoint } from '../Checkpoint';
import { PolymathError } from '../../PolymathError';
Expand Down Expand Up @@ -223,4 +218,52 @@ export class Shareholders extends SubModule {

return shareholders;
};

/**
* Retrieve the amount of wallets that ever held tokens or have any KYC data
*/
public allTimeInvestorCount = async (): Promise<number> => {
const {
context: { contractWrappers },
securityToken: { symbol },
} = this;

let securityTokenInstance;

try {
securityTokenInstance = await contractWrappers.tokenFactory.getSecurityTokenInstanceFromTicker(
symbol
);
} catch (err) {
throw new PolymathError({
code: ErrorCode.FetcherValidationError,
message: `There is no Security Token with symbol ${symbol}`,
});
}
return securityTokenInstance.getInvestorCount();
};

/**
* Retrieve the amount of wallets that currently hold tokens
*/
public holderCount = async (): Promise<number> => {
const {
context: { contractWrappers },
securityToken: { symbol },
} = this;

let securityTokenInstance;

try {
securityTokenInstance = await contractWrappers.tokenFactory.getSecurityTokenInstanceFromTicker(
symbol
);
} catch (err) {
throw new PolymathError({
code: ErrorCode.FetcherValidationError,
message: `There is no Security Token with symbol ${symbol}`,
});
}
return securityTokenInstance.holderCount();
};
}
64 changes: 64 additions & 0 deletions src/procedures/RemoveDocument.ts
@@ -0,0 +1,64 @@
import { Procedure } from './Procedure';
import {
ProcedureType,
PolyTransactionTag,
RemoveDocumentProcedureArgs,
ErrorCode,
} from '../types';
import { PolymathError } from '../PolymathError';

export class RemoveDocument extends Procedure<RemoveDocumentProcedureArgs> {
public type = ProcedureType.RemoveDocument;

public async prepareTransactions() {
const { symbol, name } = this.args;
const { contractWrappers, currentWallet } = this.context;

let securityToken;

try {
securityToken = await contractWrappers.tokenFactory.getSecurityTokenInstanceFromTicker(
symbol
);
} catch (err) {
throw new PolymathError({
code: ErrorCode.ProcedureValidationError,
message: `There is no Security Token with symbol ${symbol}`,
});
}

const [owner, account, allDocumentsList] = await Promise.all([
securityToken.owner(),
currentWallet.address(),
securityToken.getAllDocuments(),
]);

if (account !== owner) {
throw new PolymathError({
code: ErrorCode.ProcedureValidationError,
message: `You must be the owner of this Security Token to remove a document`,
});
}

if (name.length < 1 || name.length > 32) {
throw new PolymathError({
code: ErrorCode.ProcedureValidationError,
message: `You must provide a valid name between 1 and 32 characters long`,
});
}

if (!allDocumentsList.includes(name)) {
throw new PolymathError({
code: ErrorCode.ProcedureValidationError,
message: `The document you are trying to remove does not exist on this security token`,
});
}

/**
* Transactions
*/
await this.addTransaction(securityToken.removeDocument, {
tag: PolyTransactionTag.RemoveDocument,
})({ name });
}
}
55 changes: 55 additions & 0 deletions src/procedures/SetDocument.ts
@@ -0,0 +1,55 @@
import { Procedure } from './Procedure';
import { ProcedureType, PolyTransactionTag, SetDocumentProcedureArgs, ErrorCode } from '../types';
import { PolymathError } from '../PolymathError';

export class SetDocument extends Procedure<SetDocumentProcedureArgs> {
public type = ProcedureType.SetDocument;

public async prepareTransactions() {
const { symbol, name, uri, documentHash } = this.args;
const { contractWrappers, currentWallet } = this.context;

let securityToken;

try {
securityToken = await contractWrappers.tokenFactory.getSecurityTokenInstanceFromTicker(
symbol
);
} catch (err) {
throw new PolymathError({
code: ErrorCode.ProcedureValidationError,
message: `There is no Security Token with symbol ${symbol}`,
});
}

const [owner, account] = await Promise.all([securityToken.owner(), currentWallet.address()]);

if (account !== owner) {
throw new PolymathError({
code: ErrorCode.ProcedureValidationError,
message: `You must be the owner of this Security Token to set the document`,
});
}

if (name.length < 1 || name.length > 32) {
throw new PolymathError({
code: ErrorCode.ProcedureValidationError,
message: `You must provide a valid name between 1 and 32 characters long`,
});
}

if (documentHash.length < 1 || documentHash.length > 32) {
throw new PolymathError({
code: ErrorCode.ProcedureValidationError,
message: `You must provide a valid document hash between between 1 and 32 characters long`,
});
}

/**
* Transactions
*/
await this.addTransaction(securityToken.setDocument, {
tag: PolyTransactionTag.SetDocument,
})({ name, uri, documentHash });
}
}

0 comments on commit 64aa648

Please sign in to comment.