Skip to content

Commit ca96112

Browse files
committed
feat: add procedure to launch a USD Tiered STO
also renamed some types and procedure params to make them more understandable
1 parent 79a3521 commit ca96112

File tree

7 files changed

+244
-34
lines changed

7 files changed

+244
-34
lines changed

src/Polymath.ts

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ import {
2222
ErrorCode,
2323
ModuleOperation,
2424
DividendModuleType,
25-
FundraiseType,
25+
Currency,
26+
CappedStoCurrency,
2627
StoModuleType,
27-
CappedStoFundraiseType,
28+
StoTier,
2829
} from './types';
2930
import {
3031
Dividend as DividendEntity,
@@ -58,6 +59,7 @@ import {
5859
PauseSto,
5960
SetController,
6061
LaunchCappedSto,
62+
LaunchUsdTieredSto,
6163
} from './procedures';
6264
import { Entity } from './entities/Entity';
6365
import { DividendsModule } from './entities/DividendsModule';
@@ -204,22 +206,22 @@ export class Polymath {
204206
* Launch a Capped STO
205207
*
206208
* @param securityTokenId token uuid
207-
* @param startTime date when the STO should start
208-
* @param endTime date when the STO should end
209-
* @param cap amount to be raised
209+
* @param startDate date when the STO should start
210+
* @param endDate date when the STO should end
211+
* @param tokensOnSale amount of tokens to be sold
210212
* @param rate amount of tokens an investor can purchase per unit of currency spent
211-
* @param fundRaiseType currency in which the funds will be raised (ETH, POLY)
212-
* @param fundsReceiver wallet address that will receive the funds that are being raised
213+
* @param currency currency in which the funds will be raised (ETH or POLY)
214+
* @param storageWallet wallet address that will receive the funds that are being raised
213215
*
214216
*/
215217
public launchCappedSto = async (args: {
216218
securityTokenId: string;
217-
startTime: Date;
218-
endTime: Date;
219-
cap: BigNumber;
219+
startDate: Date;
220+
endDate: Date;
221+
tokensOnSale: BigNumber;
220222
rate: BigNumber;
221-
fundRaiseType: CappedStoFundraiseType;
222-
fundsReceiver: string;
223+
currency: CappedStoCurrency;
224+
storageWallet: string;
223225
}) => {
224226
const { securityTokenId, ...rest } = args;
225227
const { symbol } = this.SecurityToken.unserialize(securityTokenId);
@@ -233,6 +235,49 @@ export class Polymath {
233235
return await procedure.prepare();
234236
};
235237

238+
/**
239+
* Launch a USD Tiered STO
240+
*
241+
* @param securityTokenId token uuid
242+
* @param startDate date when the STO should start
243+
* @param endDate date when the STO should end
244+
* @param tiers tier information
245+
* @param tiers[].tokensOnSale amount of tokens to be sold on that tier
246+
* @param tiers[].price price of each token on that tier in USD
247+
* @param tiers[].tokensWithDiscount amount of tokens to be sold on that tier at a discount if paid in POLY (must be less than tokensOnSale)
248+
* @param tiers[].discountedPrice price of discounted tokens on that tier
249+
* @param nonAccreditedInvestmentLimit maximum investment for non-accredited investors
250+
* @param minimumInvestment minimum investment amount
251+
* @param currencies array of currencies in which the funds will be raised (ETH, POLY, StableCoin)
252+
* @param storageWallet wallet address that will receive the funds that are being raised
253+
* @param treasuryWallet wallet address that will receive unsold tokens when the end date is reached
254+
* @param usdTokenAddresses array of USD stable coins that the offering supports
255+
*
256+
*/
257+
public launchUsdTieredSto = async (args: {
258+
securityTokenId: string;
259+
startDate: Date;
260+
endDate: Date;
261+
tiers: StoTier[];
262+
nonAccreditedInvestmentLimit: BigNumber;
263+
minimumInvestment: BigNumber;
264+
currencies: Currency[];
265+
storageWallet: string;
266+
treasuryWallet: string;
267+
usdTokenAddresses: string[];
268+
}) => {
269+
const { securityTokenId, ...rest } = args;
270+
const { symbol } = this.SecurityToken.unserialize(securityTokenId);
271+
const procedure = new LaunchUsdTieredSto(
272+
{
273+
symbol,
274+
...rest,
275+
},
276+
this.context
277+
);
278+
return await procedure.prepare();
279+
};
280+
236281
/**
237282
* Enable dividend modules (ERC20, ETH or both)
238283
*
@@ -931,7 +976,7 @@ export class Polymath {
931976

932977
stoModules.push(
933978
new this.CappedStoModule({
934-
fundraiseTypes: isRaisedInPoly ? [FundraiseType.POLY] : [FundraiseType.ETH],
979+
fundraiseTypes: isRaisedInPoly ? [Currency.POLY] : [Currency.ETH],
935980
raisedAmount: fundsRaised,
936981
soldTokensAmount: totalTokensSold,
937982
investorAmount: investorCount,
@@ -996,15 +1041,15 @@ export class Polymath {
9961041
const fundraiseTypes = [];
9971042

9981043
if (isRaisedInETH) {
999-
fundraiseTypes.push(FundraiseType.ETH);
1044+
fundraiseTypes.push(Currency.ETH);
10001045
}
10011046

10021047
if (isRaisedInPOLY) {
1003-
fundraiseTypes.push(FundraiseType.POLY);
1048+
fundraiseTypes.push(Currency.POLY);
10041049
}
10051050

10061051
if (isRaisedInSC) {
1007-
fundraiseTypes.push(FundraiseType.StableCoin);
1052+
fundraiseTypes.push(Currency.StableCoin);
10081053
}
10091054

10101055
stoModules.push(

src/entities/StoModule.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { BigNumber } from '@polymathnetwork/contract-wrappers';
22
import { Polymath } from '../Polymath';
33
import { Entity } from './Entity';
44
import { unserialize } from '../utils';
5-
import { StoModuleType, isStoModuleType, FundraiseType } from '../types';
5+
import { StoModuleType, isStoModuleType, Currency } from '../types';
66
import { Investment } from './Investment';
77

88
export interface UniqueIdentifiers {
@@ -23,7 +23,7 @@ export interface Params extends UniqueIdentifiers {
2323
securityTokenSymbol: string;
2424
startTime: Date;
2525
endTime: Date;
26-
fundraiseTypes: FundraiseType[];
26+
fundraiseTypes: Currency[];
2727
raisedAmount: BigNumber;
2828
soldTokensAmount: BigNumber;
2929
investorAmount: number;
@@ -55,7 +55,7 @@ export abstract class StoModule extends Entity {
5555

5656
public investments: Investment[];
5757

58-
public fundraiseTypes: FundraiseType[];
58+
public fundraiseTypes: Currency[];
5959

6060
public paused: boolean;
6161

src/procedures/Approve.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export class Approve extends Procedure<ApproveProcedureArgs> {
7676
}
7777

7878
await this.addTransaction(token.approve, {
79-
tag: PolyTransactionTag.Approve,
79+
tag: PolyTransactionTag.ApprovePoly,
8080
})({ spender, value: amount });
8181
}
8282
}

src/procedures/LaunchCappedSto.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export class LaunchCappedSto extends Procedure<LaunchCappedStoProcedureArgs> {
2727
public type = ProcedureType.LaunchCappedSto;
2828

2929
public async prepareTransactions() {
30-
const { symbol, ...data } = this.args;
30+
const { symbol, startDate, endDate, tokensOnSale, rate, currency, storageWallet } = this.args;
3131
const { contractWrappers } = this.context;
3232

3333
let securityToken;
@@ -55,7 +55,7 @@ export class LaunchCappedSto extends Procedure<LaunchCappedStoProcedureArgs> {
5555
const cost = await moduleFactory.setupCostInPoly();
5656

5757
await this.addTransaction(contractWrappers.polyToken.transfer, {
58-
tag: PolyTransactionTag.Transfer,
58+
tag: PolyTransactionTag.TransferPoly,
5959
})({
6060
to: tokenAddress,
6161
value: cost,
@@ -66,7 +66,14 @@ export class LaunchCappedSto extends Procedure<LaunchCappedStoProcedureArgs> {
6666
})({
6767
moduleName,
6868
address: factoryAddress,
69-
data,
69+
data: {
70+
startTime: startDate,
71+
endTime: endDate,
72+
cap: tokensOnSale,
73+
rate,
74+
fundRaiseType: currency,
75+
fundsReceiver: storageWallet,
76+
},
7077
archived: false,
7178
});
7279
}

src/procedures/LaunchUsdTieredSto.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { ModuleName, BigNumber, FundRaiseType } from '@polymathnetwork/contract-wrappers';
2+
import { Procedure } from './Procedure';
3+
import {
4+
ProcedureType,
5+
PolyTransactionTag,
6+
ErrorCode,
7+
LaunchUsdTieredStoProcedureArgs,
8+
} from '../types';
9+
import { PolymathError } from '../PolymathError';
10+
11+
interface AddUSDTieredSTOParams {
12+
moduleName: ModuleName.UsdTieredSTO;
13+
address: string;
14+
data: {
15+
startTime: Date;
16+
endTime: Date;
17+
ratePerTier: BigNumber[];
18+
ratePerTierDiscountPoly: BigNumber[];
19+
tokensPerTierTotal: BigNumber[];
20+
tokensPerTierDiscountPoly: BigNumber[];
21+
nonAccreditedLimitUSD: BigNumber;
22+
minimumInvestmentUSD: BigNumber;
23+
fundRaiseTypes: FundRaiseType[];
24+
wallet: string;
25+
treasuryWallet: string;
26+
usdTokens: string[];
27+
};
28+
archived: boolean;
29+
label?: string;
30+
}
31+
32+
export class LaunchUsdTieredSto extends Procedure<LaunchUsdTieredStoProcedureArgs> {
33+
public type = ProcedureType.LaunchUsdTieredSto;
34+
35+
public async prepareTransactions() {
36+
const {
37+
symbol,
38+
startDate,
39+
endDate,
40+
tiers,
41+
nonAccreditedInvestmentLimit,
42+
minimumInvestment,
43+
currencies,
44+
storageWallet,
45+
treasuryWallet,
46+
usdTokenAddresses,
47+
} = this.args;
48+
const { contractWrappers } = this.context;
49+
50+
let securityToken;
51+
52+
try {
53+
securityToken = await contractWrappers.tokenFactory.getSecurityTokenInstanceFromTicker(
54+
symbol
55+
);
56+
} catch (err) {
57+
throw new PolymathError({
58+
code: ErrorCode.ProcedureValidationError,
59+
message: `There is no Security Token with symbol ${symbol}`,
60+
});
61+
}
62+
63+
const tokenAddress = await securityToken.address();
64+
const moduleName = ModuleName.UsdTieredSTO;
65+
66+
const factoryAddress = await contractWrappers.getModuleFactoryAddress({
67+
tokenAddress,
68+
moduleName,
69+
});
70+
71+
const moduleFactory = await contractWrappers.moduleFactory.getModuleFactory(factoryAddress);
72+
const cost = await moduleFactory.setupCostInPoly();
73+
74+
await this.addTransaction(contractWrappers.polyToken.transfer, {
75+
tag: PolyTransactionTag.TransferPoly,
76+
})({
77+
to: tokenAddress,
78+
value: cost,
79+
});
80+
81+
const ratePerTier: BigNumber[] = [];
82+
const ratePerTierDiscountPoly: BigNumber[] = [];
83+
const tokensPerTierTotal: BigNumber[] = [];
84+
const tokensPerTierDiscountPoly: BigNumber[] = [];
85+
86+
tiers.forEach(
87+
({
88+
tokensOnSale,
89+
price,
90+
tokensWithDiscount = new BigNumber(0),
91+
discountedPrice = new BigNumber(0),
92+
}) => {
93+
ratePerTier.push(price);
94+
ratePerTierDiscountPoly.push(discountedPrice);
95+
tokensPerTierTotal.push(tokensOnSale);
96+
tokensPerTierDiscountPoly.push(tokensWithDiscount);
97+
}
98+
);
99+
100+
await this.addTransaction<AddUSDTieredSTOParams>(securityToken.addModuleWithLabel, {
101+
tag: PolyTransactionTag.EnableCappedSto,
102+
})({
103+
moduleName,
104+
address: factoryAddress,
105+
data: {
106+
startTime: startDate,
107+
endTime: endDate,
108+
ratePerTier,
109+
ratePerTierDiscountPoly,
110+
tokensPerTierTotal,
111+
tokensPerTierDiscountPoly,
112+
nonAccreditedLimitUSD: nonAccreditedInvestmentLimit,
113+
minimumInvestmentUSD: minimumInvestment,
114+
fundRaiseTypes: currencies,
115+
wallet: storageWallet,
116+
treasuryWallet,
117+
usdTokens: usdTokenAddresses,
118+
},
119+
archived: false,
120+
});
121+
}
122+
}

src/procedures/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ export { ControllerTransfer } from './ControllerTransfer';
1616
export { PauseSto } from './PauseSto';
1717
export { SetController } from './SetController';
1818
export { LaunchCappedSto } from './LaunchCappedSto';
19+
export { LaunchUsdTieredSto } from './LaunchUsdTieredSto';

0 commit comments

Comments
 (0)