Skip to content

Commit

Permalink
Merge branch 'beta' into fix/lint-project
Browse files Browse the repository at this point in the history
  • Loading branch information
monitz87 committed Dec 30, 2019
2 parents 6a5b13b + 54eae96 commit 525e8e2
Show file tree
Hide file tree
Showing 23 changed files with 1,479 additions and 87 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@polymathnetwork/sdk",
"version": "2.0.1-beta.82",
"version": "2.0.1-beta.86",
"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
19 changes: 17 additions & 2 deletions src/entities/SecurityToken/Controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
SetController,
ControllerRedeem,
DisableController,
SignDisableControllerAck,
} from '../../procedures';

export class Controller extends SubModule {
Expand All @@ -21,9 +22,10 @@ export class Controller extends SubModule {

/**
* Permanently disable controller functionality
* @param signature optional signed data. If not passed, signing will be requested on the spot
*
* @param signature optional signed data. If not passed, signing will be requested when the transaction queue is run. The data can be generated beforehand by the token owner calling `signDisableAck`
*/
public disableController = async (args?: { signature?: string }) => {
public disable = async (args?: { signature?: string }) => {
const { symbol } = this.securityToken;
const procedure = new DisableController({ ...args, symbol }, this.context);
return procedure.prepare();
Expand Down Expand Up @@ -79,4 +81,17 @@ export class Controller extends SubModule {

return procedure.prepare();
};

/**
* Generate a signature string that can be used to permanently disable the Security Token's controller functionality
*
* Note that only the owner's signature is valid for this operation
*/
public signDisableAck = async () => {
const { symbol } = this.securityToken;

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

return procedure.prepare();
};
}
93 changes: 92 additions & 1 deletion src/entities/SecurityToken/Documents.ts
Original file line number Diff line number Diff line change
@@ -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 })));
};
}
22 changes: 20 additions & 2 deletions src/entities/SecurityToken/Issuance/Issuance.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { SubModule } from '../SubModule';
import { FreezeIssuance, IssueTokens } from '../../../procedures';
import { FreezeIssuance, IssueTokens, SignFreezeIssuanceAck } from '../../../procedures';
import { ErrorCode, IssuanceDataEntry } from '../../../types';
import { Offerings } from './Offerings';
import { SecurityToken } from '../SecurityToken';
import { Context } from '../../../Context';

import { PolymathError } from '../../../PolymathError';

export class Issuance extends SubModule {
Expand All @@ -18,6 +19,7 @@ export class Issuance extends SubModule {
/**
* Issue a certain amount of tokens to an address. The address must already have been added via `modifyData`. Otherwise,
* the corresponding shareholder data for that address must be supplied to this method
* NOTE: If shareholder data is supplied, client-side validations to verify if the transfer is possible won't be performed
*
* @param issuanceData array of issuance data
* @param issuanceData[].address address of the shareholder to issue tokens for
Expand All @@ -42,11 +44,27 @@ export class Issuance extends SubModule {

/**
* Permanently freeze issuance of the security token
* @param signature optional signed data. If not passed, signing will be requested on the spot
*
* @param signature optional signed data. If not passed, signing will be requested when the transaction queue is run. The data can be generated beforehand by the token owner calling `signFreezeAck`
*/
public freeze = async (args?: { signature?: string }) => {
const { symbol } = this.securityToken;

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

return procedure.prepare();
};

/**
* Generate a signature string that can be used to permanently freeze issuance of the Security Token
*
* Note that only the owner's signature is valid for this operation
*/
public signFreezeAck = async () => {
const { symbol } = this.securityToken;

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

return procedure.prepare();
};

Expand Down
48 changes: 48 additions & 0 deletions src/entities/SecurityToken/Shareholders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,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();
};
}
46 changes: 43 additions & 3 deletions src/entities/SecurityToken/Transfers/Transfers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import { SubModule } from '../SubModule';
import { Restrictions } from './Restrictions';
import { SecurityToken } from '../SecurityToken';
import { Context } from '../../../Context';
import { TransferSecurityTokens } from '../../../procedures/TransferSecurityTokens';
import { TransferStatusCode, ErrorCode } from '../../../types';
import { ToggleFreezeTransfers } from '../../../procedures/ToggleFreezeTransfers';
import {
SignTransferData,
TransferSecurityTokens,
ToggleFreezeTransfers,
} from '../../../procedures';
import { ShareholderDataEntry, Omit, TransferStatusCode, ErrorCode } from '../../../types';
import { PolymathError } from '../../../PolymathError';

export class Transfers extends SubModule {
Expand All @@ -21,6 +24,43 @@ export class Transfers extends SubModule {
}

/**
* Generate a signature string based on dynamic KYC data. This data can be used to:
*
* - Check if a transfer can be made (using `canTransfer`) with different KYC data than is currently present
* - Actually make a transfer (using `transfer`) with different KYC data than is currently present (in this case, the existing KYC data will be overwritten)
*
* The signature can be generated by a third party other than the issuer. The signing wallet should have permission to modify KYC data (via the Shareholders Administrator role).
* Otherwise, the new data will be disregarded
*
* Note that, when supplying KYC data for signing, ALL investor entries should be supplied (even those that remain the same)
*
* @param kycData new KYC data array to sign
* @param kycData[].address shareholder wallet address
* @param kycData[].canSendAfter date after which the shareholder can transfer tokens (sell lockup)
* @param kycData[].canReceiveAfter date after which the shareholder can receive tokens (buy lockup)
* @param kycData[].kycExpiry date at which the shareholder's KYC expires
* @param validFrom date from which this signature is valid
* @param validTo date until which this signature is valid
*/
public signKycData = async (args: {
kycData: Omit<Omit<ShareholderDataEntry, 'canBuyFromSto'>, 'isAccredited'>[];
validFrom: Date;
validTo: Date;
}) => {
const { context, securityToken } = this;
const { symbol } = securityToken;
const procedure = new SignTransferData(
{
symbol,
...args,
},
context
);
return procedure.prepare();
};

/**
* Transfer security token
* Transfer an amount of Security Tokens to a specified address
*
* @param to address that will receive the tokens
Expand Down
13 changes: 12 additions & 1 deletion src/entities/SecurityTokenReservation.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Entity } from './Entity';
import { serialize, unserialize } from '../utils';
import { Context } from '../Context';
import { CreateSecurityToken } from '../procedures';
import { CreateSecurityToken, TransferReservationOwnership } from '../procedures';
import { PolymathError } from '../PolymathError';
import { ErrorCode } from '../types';

Expand Down Expand Up @@ -115,6 +115,17 @@ export class SecurityTokenReservation extends Entity<Params> {
return context.contractWrappers.securityTokenRegistry.isTokenLaunched({ ticker: symbol });
};

/**
* Transfer the ownership of the ticker
*/
public transferOwnership = async (args: { newOwner: string }) => {
const { context, symbol } = this;
const { newOwner } = args;
const procedure = new TransferReservationOwnership({ symbol, newOwner }, context);

return procedure.prepare();
};

public toPojo() {
const { uid, symbol, expiry, securityTokenAddress, reservedAt, ownerAddress } = this;

Expand Down
Loading

0 comments on commit 525e8e2

Please sign in to comment.