Skip to content
This repository has been archived by the owner on Jul 6, 2022. It is now read-only.

Commit

Permalink
Merge 94025d2 into cddd553
Browse files Browse the repository at this point in the history
  • Loading branch information
shuffledex committed Aug 2, 2019
2 parents cddd553 + 94025d2 commit 9952312
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 22 deletions.
4 changes: 2 additions & 2 deletions examples/countTransferManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,13 @@ window.addEventListener('load', async () => {
];

// Call to add count transfer manager module with max 3 holders
await tickerSecurityTokenInstance.addModule({
await tickerSecurityTokenInstance.addModuleWithLabel({
moduleName,
address: modules[index],
maxCost: setupCost,
budget: setupCost,
archived: false,
label: 'CTM Test',
data: {
maxHolderCount: randomBeneficiaries.length + 1,
},
Expand Down Expand Up @@ -140,7 +141,6 @@ window.addEventListener('load', async () => {
await tickerSecurityTokenInstance.issue({
investor: myAddress,
value: new BigNumber(200),
data: '0x00',
});

// Add beneficiaries address to whitelist
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
Partition,
Perm,
CappedSTOFundRaiseType,
TransferStatusCode
} from '../../../types';
import SecurityTokenWrapper from '../security_token_wrapper';
import ContractFactory from '../../../factories/contractFactory';
Expand Down Expand Up @@ -950,7 +951,7 @@ describe('SecurityTokenWrapper', () => {
test.todo('should fail as granularity is a zero big number');

test('should call to canTransferFrom', async () => {
const expectedStatusCode = 'X';
const expectedStatusCode = TransferStatusCode.TransferSuccess;
const expectedReasonCode = 'Reason';
const expectedResult = [expectedStatusCode, stringToBytes32(expectedReasonCode)];

Expand Down Expand Up @@ -1005,7 +1006,7 @@ describe('SecurityTokenWrapper', () => {
test.todo('should fail as granularity is a zero big number');

test('should call to canTransfer', async () => {
const expectedStatusCode = 'X';
const expectedStatusCode = TransferStatusCode.TransferSuccess;
const expectedReasonCode = 'Reason';
const expectedResult = [expectedStatusCode, stringToBytes32(expectedReasonCode)];

Expand Down Expand Up @@ -1058,7 +1059,7 @@ describe('SecurityTokenWrapper', () => {
test.todo('should fail as granularity is a zero big number');

test('should call to canTransferByPartition', async () => {
const expectedStatusCode = 'X';
const expectedStatusCode = TransferStatusCode.TransferSuccess;
const expectedReasonCode = 'Reason';
const expectedPartition = Partition.Unlocked;
const expectedResult = [
Expand Down Expand Up @@ -2532,9 +2533,9 @@ describe('SecurityTokenWrapper', () => {
test('should send the transaction to issue', async () => {
// Mocked parameters
const mockedParams = {
investor: '0x1111111111111111111111111111111111111111',
investor: '0x1234111111111111111111111111111111111111',
value: new BigNumber(2),
data: 'string',
data: '0x00',
txData: {},
safetyFactor: 10,
};
Expand Down Expand Up @@ -2571,16 +2572,28 @@ describe('SecurityTokenWrapper', () => {
// Mock web3 wrapper owner
when(mockedWrapper.getAvailableAddressesAsync()).thenResolve([expectedOwnerResult]);

// canTransfer
const expectedStatusCode = TransferStatusCode.TransferSuccess;
const expectedReasonCode = 'Reason';
const expectedCanResult = [expectedStatusCode, stringToBytes32(expectedReasonCode)];

const mockedCanMethod = mock(MockedCallMethod);
when(mockedContract.canTransfer).thenReturn(instance(mockedCanMethod));
when(mockedCanMethod.callAsync(
mockedParams.investor,
objectContaining(valueToWei(mockedParams.value, expectedDecimalsResult)),
mockedParams.data
)).thenResolve(expectedCanResult);

const expectedIsIssuableResult = true;
// Mocked method
const mockedIsIssuableMethod = mock(MockedCallMethod);
// Stub the method
when(mockedContract.isIssuable).thenReturn(instance(mockedIsIssuableMethod));
// Stub the request
when(mockedIsIssuableMethod.callAsync()).thenResolve(expectedIsIssuableResult);

// Real call
const result = await target.issue(mockedParams);
const result = await target.issue(mockedParams);

// Result expectation
expect(result).toBe(expectedResult);
Expand All @@ -2600,8 +2613,14 @@ describe('SecurityTokenWrapper', () => {
verify(mockedContract.isIssuable).once();
verify(mockedIsIssuableMethod.callAsync()).once();
verify(mockedWrapper.getAvailableAddressesAsync()).once();
verify(mockedContract.decimals).once();
verify(mockedDecimalsMethod.callAsync()).once();
verify(mockedContract.decimals).twice();
verify(mockedDecimalsMethod.callAsync()).twice();
verify(mockedContract.canTransfer).once();
verify(mockedCanMethod.callAsync(
mockedParams.investor,
objectContaining(valueToWei(mockedParams.value, expectedDecimalsResult)),
mockedParams.data
)).once();
});
});

Expand Down Expand Up @@ -3559,7 +3578,7 @@ describe('SecurityTokenWrapper', () => {
objectContaining(ctmData),
objectContaining(valueToWei(mockedCtmParams.maxCost, FULL_DECIMALS)),
objectContaining(valueToWei(mockedCtmParams.budget, FULL_DECIMALS)),
objectContaining(mockedCtmParams.label),
stringToBytes32(mockedCtmParams.label),
mockedCtmParams.archived,
mockedCtmParams.txData,
mockedCtmParams.safetyFactor,
Expand Down Expand Up @@ -3587,7 +3606,7 @@ describe('SecurityTokenWrapper', () => {
objectContaining(ctmData),
objectContaining(valueToWei(mockedCtmParams.maxCost, FULL_DECIMALS)),
objectContaining(valueToWei(mockedCtmParams.budget, FULL_DECIMALS)),
objectContaining(mockedCtmParams.label),
stringToBytes32(mockedCtmParams.label),
mockedCtmParams.archived,
mockedCtmParams.txData,
mockedCtmParams.safetyFactor,
Expand Down
73 changes: 64 additions & 9 deletions src/contract_wrappers/tokens/security_token_wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import {
SubscribeAsyncParams,
TxParams,
CappedSTOFundRaiseType,
TransferStatusCode
} from '../../types';
import {
bigNumberToDate,
Expand Down Expand Up @@ -620,7 +621,7 @@ interface TransferFromWithDataParams extends TxParams {
interface IssueParams extends TxParams {
investor: string;
value: BigNumber;
data: string;
data?: string;
}

interface IssueByPartitionParams extends IssueParams {
Expand Down Expand Up @@ -848,7 +849,7 @@ interface DocumentData {

interface CanTransferFromData {
/** Status Code */
statusCode: string;
statusCode: TransferStatusCode;
/** Reason Code */
reasonCode: string;
}
Expand Down Expand Up @@ -1220,10 +1221,16 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
assert.isNonZeroETHAddressHex('investor', params.investor);
await this.checkOnlyOwner(params.txData);
assert.assert(await this.isIssuable(), 'Issuance frozen');
const canTransfer = await this.canTransfer({
to: params.investor,
value: params.value,
data: params.data || '0x00'
});
assert.assert(canTransfer.statusCode !== TransferStatusCode.TransferFailure, `Transfer Status: ${canTransfer.statusCode}`)
return (await this.contract).issue.sendTransactionAsync(
params.investor,
valueToWei(params.value, await this.decimals()),
params.data,
params.data || '0x00',
params.txData,
params.safetyFactor,
);
Expand All @@ -1238,7 +1245,7 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
params.partition,
params.investor,
valueToWei(params.value, await this.decimals()),
params.data,
params.data || '0x00',
params.txData,
params.safetyFactor,
);
Expand Down Expand Up @@ -1531,7 +1538,7 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
producedAddModuleInfo.data,
producedAddModuleInfo.maxCost,
producedAddModuleInfo.budget,
params.label ? params.label : '',
params.label ? stringToBytes32(params.label) : '',
params.archived,
params.txData,
params.safetyFactor,
Expand Down Expand Up @@ -1571,6 +1578,52 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
return typedResult;
};

private getTransferStatusCode = (result: string) => {
let status: TransferStatusCode = TransferStatusCode.TransferSuccess;
switch(result) {
case TransferStatusCode.TransferFailure: {
status = TransferStatusCode.TransferFailure;
break
}
case TransferStatusCode.TransferSuccess: {
status = TransferStatusCode.TransferSuccess;
break
}
case TransferStatusCode.InsufficientBalance: {
status = TransferStatusCode.InsufficientBalance;
break
}
case TransferStatusCode.InsufficientAllowance: {
status = TransferStatusCode.InsufficientAllowance;
break
}
case TransferStatusCode.TransfersHalted: {
status = TransferStatusCode.TransfersHalted;
break
}
case TransferStatusCode.FundsLocked: {
status = TransferStatusCode.FundsLocked;
break
}
case TransferStatusCode.InvalidSender: {
status = TransferStatusCode.InvalidSender;
break
}
case TransferStatusCode.InvalidReceiver: {
status = TransferStatusCode.InvalidReceiver;
break
}
case TransferStatusCode.InvalidOperator: {
status = TransferStatusCode.InvalidOperator;
break
}
default: {
break
}
}
return status
}

/**
* Validates if can transfer
* @return statusCode, reasonCode
Expand All @@ -1582,9 +1635,9 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
valueToWei(params.value, await this.decimals()),
params.data,
);

const status = this.getTransferStatusCode(result[0]);
const typedResult: CanTransferFromData = {
statusCode: result[0],
statusCode: status,
reasonCode: bytes32ToString(result[1]),
};
return typedResult;
Expand All @@ -1603,8 +1656,9 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
valueToWei(params.value, await this.decimals()),
params.data,
);
const status = this.getTransferStatusCode(result[0]);
const typedResult: CanTransferFromData = {
statusCode: result[0],
statusCode: status,
reasonCode: bytes32ToString(result[1]),
};
return typedResult;
Expand All @@ -1624,8 +1678,9 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
valueToWei(params.value, await this.decimals()),
params.data,
);
const status = this.getTransferStatusCode(result[0]);
const typedResult: CanTransferByPartitionData = {
statusCode: result[0],
statusCode: status,
reasonCode: bytes32ToString(result[1]),
partition: parsePartitionBytes32Value(result[2]),
};
Expand Down
12 changes: 12 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,18 @@ export enum ModuleName {
EtherDividendCheckpoint = 'EtherDividendCheckpoint',
}

export enum TransferStatusCode {
TransferFailure = '0x50',
TransferSuccess = '0x51',
InsufficientBalance = '0x52',
InsufficientAllowance = '0x53',
TransfersHalted = '0x54',
FundsLocked = '0x55',
InvalidSender = '0x56',
InvalidReceiver = '0x57',
InvalidOperator = '0x58',
}

export enum Perm {
Admin = 'ADMIN',
Operator = 'OPERATOR',
Expand Down

0 comments on commit 9952312

Please sign in to comment.