Skip to content

Commit 3ceb5ab

Browse files
committed
feat: create procedure to allow/disallow beneficial investment
1 parent 48a8e2a commit 3ceb5ab

File tree

5 files changed

+161
-1
lines changed

5 files changed

+161
-1
lines changed

src/entities/Sto.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { StoType, isStoType, Currency, ErrorCode, StoRole } from '../types';
55
import { Investment } from './Investment';
66
import { PolymathError } from '../PolymathError';
77
import { Context } from '../Context';
8-
import { PauseSto, AssignStoRole, FinalizeSto } from '../procedures';
8+
import { PauseSto, AssignStoRole, FinalizeSto, ModifyBeneficialInvestments } from '../procedures';
99
import { ModifyPreMinting } from '../procedures/ModifyPreMinting';
1010

1111
export interface UniqueIdentifiers {
@@ -190,6 +190,34 @@ export abstract class Sto<P> extends Entity<P> {
190190
return procedure.prepare();
191191
};
192192

193+
/**
194+
* Enables a party to invest in the STO on behalf of another party
195+
*/
196+
public allowBeneficialInvestments = async () => {
197+
const { address: stoAddress, stoType, securityTokenSymbol: symbol } = this;
198+
199+
const procedure = new ModifyBeneficialInvestments(
200+
{ stoAddress, stoType, symbol, allowBeneficialInvestments: true },
201+
this.context
202+
);
203+
204+
return procedure.prepare();
205+
};
206+
207+
/**
208+
* Disables the possibility for a party to invest in the STO on behalf of another party
209+
*/
210+
public disallowBeneficialInvestments = async () => {
211+
const { address: stoAddress, stoType, securityTokenSymbol: symbol } = this;
212+
213+
const procedure = new ModifyBeneficialInvestments(
214+
{ stoAddress, stoType, symbol, allowBeneficialInvestments: false },
215+
this.context
216+
);
217+
218+
return procedure.prepare();
219+
};
220+
193221
/**
194222
* Assigns a role on the STO to a delegate
195223
*
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import { ModuleName } from '@polymathnetwork/contract-wrappers';
2+
import { Procedure } from './Procedure';
3+
import {
4+
ProcedureType,
5+
PolyTransactionTag,
6+
ModifyBeneficialInvestmentsProcedureArgs,
7+
ErrorCode,
8+
StoType,
9+
} from '../types';
10+
import { PolymathError } from '../PolymathError';
11+
import { isValidAddress } from '../utils';
12+
import { SecurityToken, CappedSto, TieredSto } from '../entities';
13+
14+
export class ModifyBeneficialInvestments extends Procedure<
15+
ModifyBeneficialInvestmentsProcedureArgs
16+
> {
17+
public type = ProcedureType.PauseSto;
18+
19+
public async prepareTransactions() {
20+
const { stoAddress, stoType, symbol, allowBeneficialInvestments } = this.args;
21+
const { contractWrappers, factories } = this.context;
22+
23+
/**
24+
* Validation
25+
*/
26+
27+
if (!isValidAddress(stoAddress)) {
28+
throw new PolymathError({
29+
code: ErrorCode.InvalidAddress,
30+
message: `Invalid STO address ${stoAddress}`,
31+
});
32+
}
33+
34+
let stoModule;
35+
36+
switch (stoType) {
37+
case StoType.Capped: {
38+
stoModule = await contractWrappers.moduleFactory.getModuleInstance({
39+
name: ModuleName.CappedSTO,
40+
address: stoAddress,
41+
});
42+
43+
break;
44+
}
45+
case StoType.Tiered: {
46+
stoModule = await contractWrappers.moduleFactory.getModuleInstance({
47+
name: ModuleName.UsdTieredSTO,
48+
address: stoAddress,
49+
});
50+
51+
break;
52+
}
53+
default: {
54+
throw new PolymathError({
55+
code: ErrorCode.ProcedureValidationError,
56+
message: `Invalid STO type ${stoType}`,
57+
});
58+
}
59+
}
60+
61+
if (!stoModule) {
62+
throw new PolymathError({
63+
code: ErrorCode.ProcedureValidationError,
64+
message: `STO ${stoAddress} is either archived or hasn't been launched`,
65+
});
66+
}
67+
68+
const beneficialInvesmentsAllowed = await stoModule.allowBeneficialInvestments();
69+
70+
if (beneficialInvesmentsAllowed === allowBeneficialInvestments) {
71+
throw new PolymathError({
72+
code: ErrorCode.ProcedureValidationError,
73+
message: `Beneficial investments are already ${
74+
beneficialInvesmentsAllowed ? '' : 'dis'
75+
}allowed`,
76+
});
77+
}
78+
79+
/**
80+
* Transactions
81+
*/
82+
83+
await this.addTransaction(stoModule.changeAllowBeneficialInvestments, {
84+
tag: PolyTransactionTag.ChangeAllowBeneficialInvestments,
85+
resolvers: [
86+
async () => {
87+
const securityTokenId = SecurityToken.generateId({ symbol });
88+
89+
switch (stoType) {
90+
case StoType.Capped: {
91+
return factories.cappedStoFactory.refresh(
92+
CappedSto.generateId({
93+
securityTokenId,
94+
stoType: StoType.Capped,
95+
address: stoAddress,
96+
})
97+
);
98+
}
99+
case StoType.Tiered: {
100+
return factories.tieredStoFactory.refresh(
101+
TieredSto.generateId({
102+
securityTokenId,
103+
stoType: StoType.Tiered,
104+
address: stoAddress,
105+
})
106+
);
107+
}
108+
}
109+
},
110+
],
111+
})({ allowBeneficialInvestments });
112+
}
113+
}

src/procedures/ModifyPreMinting.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ export class ModifyPreMinting extends Procedure<ModifyPreMintingProcedureArgs> {
7979
});
8080
}
8181

82+
const preMintingAllowed = await stoModule.preMintAllowed();
83+
84+
if (preMintingAllowed === allowPreMinting) {
85+
throw new PolymathError({
86+
code: ErrorCode.ProcedureValidationError,
87+
message: `Pre-minting is already ${preMintingAllowed ? '' : 'dis'}allowed`,
88+
});
89+
}
90+
8291
/**
8392
* Transactions
8493
*/

src/procedures/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ export { ModifyShareholderData } from './ModifyShareholderData';
2525
export { RevokeKyc } from './RevokeKyc';
2626
export { MintTokens } from './MintTokens';
2727
export { FinalizeSto } from './FinalizeSto';
28+
export { ModifyBeneficialInvestments } from './ModifyBeneficialInvestments';

src/types/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export enum ProcedureType {
147147
RevokeKyc = 'RevokeKyc',
148148
MintTokens = 'MintTokens',
149149
ModifyPreMinting = 'ModifyPreMinting',
150+
ModifyBeneficialInvestments = 'ModifyBeneificialInvestments',
150151
}
151152

152153
export enum PolyTransactionTag {
@@ -182,6 +183,7 @@ export enum PolyTransactionTag {
182183
IssueMulti = 'IssueMulti',
183184
AllowPreMinting = 'AllowPreMinting',
184185
RevokePreMinting = 'RevokePreMinting',
186+
ChangeAllowBeneficialInvestments = 'ChangeAllowBeneficialInvestments',
185187
}
186188

187189
export type MaybeResolver<T> = PostTransactionResolver<T> | T;
@@ -306,6 +308,13 @@ export interface ModifyPreMintingProcedureArgs {
306308
allowPreMinting: boolean;
307309
}
308310

311+
export interface ModifyBeneficialInvestmentsProcedureArgs {
312+
symbol: string;
313+
stoAddress: string;
314+
stoType: StoType;
315+
allowBeneficialInvestments: boolean;
316+
}
317+
309318
export interface StoTier {
310319
/**
311320
* Amount of tokens to sell in this tier

0 commit comments

Comments
 (0)