Skip to content

Commit a07db1d

Browse files
committed
feat: expose USD fees as well as POLY fees
Also added fees to STO launch procedures BREAKING CHANGE: change the `fees` property in Transaction Queues from `BigNumber` to `{ usd: BigNumber; poly: BigNumber; }`
1 parent 41a3c94 commit a07db1d

File tree

8 files changed

+101
-29
lines changed

8 files changed

+101
-29
lines changed

src/entities/TransactionQueue.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { EventEmitter } from 'events';
22
import v4 from 'uuid/v4';
3-
import { BigNumber } from '@polymathnetwork/contract-wrappers';
4-
import { TransactionSpec, MaybeResolver, ProcedureType, TransactionQueueStatus } from '../types';
3+
import {
4+
TransactionSpec,
5+
MaybeResolver,
6+
ProcedureType,
7+
TransactionQueueStatus,
8+
Fees,
9+
} from '../types';
510
import { Entity } from './Entity';
611
import { PolyTransaction } from './PolyTransaction';
712
import { isPostTransactionResolver } from '../PostTransactionResolver';
@@ -35,7 +40,7 @@ export class TransactionQueue<Args extends any = any, ReturnType extends any = v
3540

3641
public error?: Error;
3742

38-
public fees: BigNumber;
43+
public fees: Fees;
3944

4045
private promise: Promise<ReturnType>;
4146

@@ -47,7 +52,7 @@ export class TransactionQueue<Args extends any = any, ReturnType extends any = v
4752

4853
constructor(
4954
transactions: TransactionSpec[],
50-
fees: BigNumber,
55+
fees: Fees,
5156
returnValue: MaybeResolver<ReturnType>,
5257
args: Args,
5358
procedureType: ProcedureType = ProcedureType.UnnamedProcedure
@@ -78,12 +83,13 @@ export class TransactionQueue<Args extends any = any, ReturnType extends any = v
7883
}
7984

8085
public toPojo() {
81-
const { uid, transactions, status, procedureType, args } = this;
86+
const { uid, transactions, status, procedureType, args, fees } = this;
8287

8388
return {
8489
uid,
8590
transactions: transactions.map(transaction => transaction.toPojo()),
8691
status,
92+
fees,
8793
procedureType,
8894
args,
8995
};

src/entities/__tests__/TransactionQueue.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
import { BigNumber } from '@polymathnetwork/contract-wrappers';
2-
import { TransactionQueueStatus, isPojo } from '../../types';
2+
import { TransactionQueueStatus, isPojo, Fees } from '../../types';
33
import { MockedContract, getMockTransactionSpec } from '../../testUtils';
44
import { TransactionQueue } from '../TransactionQueue';
55

66
describe('TransactionQueue', () => {
77
let testContract: MockedContract;
8+
let testFees: Fees;
89

910
beforeEach(() => {
1011
testContract = new MockedContract();
12+
testFees = {
13+
usd: new BigNumber(0),
14+
poly: new BigNumber(0),
15+
};
1116
});
1217

1318
describe('constructor', () => {
1419
test('initializes properly', () => {
1520
const transaction = getMockTransactionSpec(testContract.fakeTxOne, []);
16-
const transactionQueue = new TransactionQueue([transaction], new BigNumber(0), null, {});
21+
const transactionQueue = new TransactionQueue([transaction], testFees, null, {});
1722
expect(transactionQueue).toBeInstanceOf(TransactionQueue);
1823
expect(transactionQueue.run()).toBeInstanceOf(Promise);
1924
});
@@ -25,7 +30,7 @@ describe('TransactionQueue', () => {
2530

2631
const tx1 = getMockTransactionSpec(contract.fakeTxOne, []);
2732
const tx2 = getMockTransactionSpec(contract.fakeTxTwo, []);
28-
const transactionQueue = new TransactionQueue([tx1, tx2], new BigNumber(0), null, {});
33+
const transactionQueue = new TransactionQueue([tx1, tx2], testFees, null, {});
2934

3035
const polyTx1 = transactionQueue.transactions[0];
3136
const polyTx2 = transactionQueue.transactions[1];
@@ -56,7 +61,7 @@ describe('TransactionQueue', () => {
5661
test('returns a plain object representing the entity', () => {
5762
const txOne = getMockTransactionSpec(testContract.fakeTxOne, ['stringOne']);
5863

59-
const transactionQueue = new TransactionQueue([txOne], new BigNumber(0), null, {});
64+
const transactionQueue = new TransactionQueue([txOne], testFees, null, {});
6065

6166
expect(isPojo(transactionQueue.toPojo())).toBeTruthy();
6267
});
@@ -66,7 +71,7 @@ describe('TransactionQueue', () => {
6671
test('runs the queue sequentially and resolves when done', async () => {
6772
const txOne = getMockTransactionSpec(testContract.fakeTxOne, ['stringOne']);
6873
const txTwo = getMockTransactionSpec(testContract.fakeTxTwo, ['stringTwo']);
69-
const transactionQueue = new TransactionQueue([txOne, txTwo], new BigNumber(0), null, {});
74+
const transactionQueue = new TransactionQueue([txOne, txTwo], testFees, null, {});
7075
const t1Promise = transactionQueue.transactions[0].promise;
7176
const t2Promise = transactionQueue.transactions[1].promise;
7277

@@ -88,7 +93,7 @@ describe('TransactionQueue', () => {
8893
const txOne = getMockTransactionSpec(contract.fakeTxOne, ['stringOne']);
8994
const txTwo = getMockTransactionSpec(contract.fakeTxTwo, ['stringTwo']);
9095

91-
const transactionQueue = new TransactionQueue([txOne, txTwo], new BigNumber(0), null, {});
96+
const transactionQueue = new TransactionQueue([txOne, txTwo], testFees, null, {});
9297

9398
expect(transactionQueue.status).toEqual(TransactionQueueStatus.Idle);
9499
const promise = transactionQueue.run();
@@ -110,7 +115,7 @@ describe('TransactionQueue', () => {
110115
test('sets error and status as failed if any transaction fails', async () => {
111116
const contract = new MockedContract({ autoResolve: true });
112117
const failureTx = getMockTransactionSpec(contract.failureTx, []);
113-
const transactionQueue = new TransactionQueue([failureTx], new BigNumber(0), null, {});
118+
const transactionQueue = new TransactionQueue([failureTx], testFees, null, {});
114119

115120
await expect(transactionQueue.run()).rejects.toEqual(expect.any(Error));
116121

src/procedures/CreateSecurityToken.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { SecurityTokenRegistryEvents } from '@polymathnetwork/abi-wrappers';
2+
import { FeeType } from '@polymathnetwork/contract-wrappers';
23
import { Procedure } from './Procedure';
34
import { ApproveErc20 } from './ApproveErc20';
45
import {
@@ -63,16 +64,19 @@ export class CreateSecurityToken extends Procedure<
6364
});
6465
}
6566

66-
const fee = await securityTokenRegistry.getSecurityTokenLaunchFee();
67+
const [usdFee, polyFee] = await securityTokenRegistry.getFees({ feeType: FeeType.stLaunchFee });
6768

6869
await this.addProcedure(ApproveErc20)({
69-
amount: fee,
70+
amount: polyFee,
7071
spender: await securityTokenRegistry.address(),
7172
});
7273

7374
const newToken = await this.addTransaction(securityTokenRegistry.generateNewSecurityToken, {
7475
tag: PolyTransactionTag.CreateSecurityToken,
75-
fee,
76+
fees: {
77+
usd: usdFee,
78+
poly: polyFee,
79+
},
7680
resolver: async receipt => {
7781
const { logs } = receipt;
7882

src/procedures/LaunchCappedSto.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,30 @@ export class LaunchCappedSto extends Procedure<LaunchCappedStoProcedureArgs, Cap
6565
});
6666

6767
const moduleFactory = await contractWrappers.moduleFactory.getModuleFactory(factoryAddress);
68-
const cost = await moduleFactory.setupCostInPoly();
68+
let usdCost: BigNumber | null = null;
69+
const [polyCost, isCostInPoly, cost] = await Promise.all([
70+
moduleFactory.setupCostInPoly(),
71+
moduleFactory.isCostInPoly(),
72+
moduleFactory.setupCost(),
73+
]);
74+
75+
if (!isCostInPoly) {
76+
usdCost = cost;
77+
}
6978

7079
await this.addProcedure(TransferErc20)({
7180
receiver: securityTokenAddress,
72-
amount: cost,
81+
amount: polyCost,
7382
});
7483

7584
const newSto = await this.addTransaction<AddCappedSTOParams, CappedSto>(
7685
securityToken.addModuleWithLabel,
7786
{
7887
tag: PolyTransactionTag.EnableCappedSto,
88+
fees: {
89+
usd: usdCost,
90+
poly: polyCost,
91+
},
7992
resolver: async receipt => {
8093
const { logs } = receipt;
8194

src/procedures/LaunchUsdTieredSto.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,20 @@ export class LaunchUsdTieredSto extends Procedure<LaunchUsdTieredStoProcedureArg
8282
});
8383

8484
const moduleFactory = await contractWrappers.moduleFactory.getModuleFactory(factoryAddress);
85-
const cost = await moduleFactory.setupCostInPoly();
85+
let usdCost: BigNumber | null = null;
86+
const [polyCost, isCostInPoly, cost] = await Promise.all([
87+
moduleFactory.setupCostInPoly(),
88+
moduleFactory.isCostInPoly(),
89+
moduleFactory.setupCost(),
90+
]);
91+
92+
if (!isCostInPoly) {
93+
usdCost = cost;
94+
}
8695

8796
await this.addProcedure(TransferErc20)({
8897
receiver: securityTokenAddress,
89-
amount: cost,
98+
amount: polyCost,
9099
});
91100

92101
const ratePerTier: BigNumber[] = [];
@@ -112,6 +121,10 @@ export class LaunchUsdTieredSto extends Procedure<LaunchUsdTieredStoProcedureArg
112121
securityToken.addModuleWithLabel,
113122
{
114123
tag: PolyTransactionTag.EnableUsdTieredSto,
124+
fees: {
125+
usd: usdCost,
126+
poly: polyCost,
127+
},
115128
resolver: async receipt => {
116129
const { logs } = receipt;
117130

src/procedures/Procedure.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
MaybeResolver,
88
ProcedureType,
99
PolyTransactionTag,
10+
Fees,
1011
} from '../types';
1112
import { TransactionQueue } from '../entities/TransactionQueue';
1213
import { Context } from '../Context';
@@ -27,7 +28,7 @@ export abstract class Procedure<Args, ReturnType = void> {
2728

2829
private transactions: TransactionSpec[] = [];
2930

30-
private fees: Array<BigNumber> = [];
31+
private fees: Array<Fees> = [];
3132

3233
constructor(args: Args, context: Context) {
3334
this.args = args;
@@ -40,7 +41,23 @@ export abstract class Procedure<Args, ReturnType = void> {
4041
*/
4142
public prepare = async () => {
4243
const returnValue = await this.prepareTransactions();
43-
const totalFees = this.fees.reduce((total, fee) => total.plus(fee), new BigNumber(0));
44+
const totalFees = this.fees.reduce(
45+
({ usd, poly }, { usd: newUsd, poly: newPoly }) => {
46+
const polySum = poly.plus(newPoly);
47+
let usdSum;
48+
if (usd === null && newUsd === null) {
49+
usdSum = null;
50+
} else {
51+
usdSum = (usd || new BigNumber(0)).plus(newUsd || new BigNumber(0));
52+
}
53+
54+
return {
55+
usd: usdSum,
56+
poly: polySum,
57+
};
58+
},
59+
{ usd: null, poly: new BigNumber(0) }
60+
);
4461

4562
const transactionQueue = new TransactionQueue(
4663
this.transactions,
@@ -105,19 +122,19 @@ export abstract class Procedure<Args, ReturnType = void> {
105122
method: LowLevelMethod<A>,
106123
{
107124
tag,
108-
fee,
125+
fees,
109126
resolver = (() => {}) as () => Promise<R>,
110127
}: {
111128
tag?: PolyTransactionTag;
112-
fee?: BigNumber;
129+
fees?: Fees;
113130
resolver?: (receipt: TransactionReceiptWithDecodedLogs) => Promise<R>;
114131
} = {}
115132
) => {
116133
return async (args: MapMaybeResolver<A>) => {
117134
const postTransactionResolver = new PostTransactionResolver(resolver);
118135

119-
if (fee) {
120-
this.fees.push(fee);
136+
if (fees) {
137+
this.fees.push(fees);
121138
}
122139

123140
const transaction = {

src/procedures/ReserveSecurityToken.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { SecurityTokenRegistryEvents, conversionUtils } from '@polymathnetwork/contract-wrappers';
1+
import {
2+
SecurityTokenRegistryEvents,
3+
conversionUtils,
4+
FeeType,
5+
} from '@polymathnetwork/contract-wrappers';
26
import { Procedure } from './Procedure';
37
import { ApproveErc20 } from './ApproveErc20';
48
import {
@@ -47,15 +51,20 @@ export class ReserveSecurityToken extends Procedure<
4751
});
4852
}
4953

50-
const fee = await securityTokenRegistry.getTickerRegistrationFee();
54+
const [usdFee, polyFee] = await securityTokenRegistry.getFees({
55+
feeType: FeeType.tickerRegFee,
56+
});
5157
await addProcedure(ApproveErc20)({
52-
amount: fee,
58+
amount: polyFee,
5359
spender: await securityTokenRegistry.address(),
5460
});
5561

5662
const reservation = await addTransaction(securityTokenRegistry.registerNewTicker, {
5763
tag: PolyTransactionTag.ReserveSecurityToken,
58-
fee,
64+
fees: {
65+
poly: polyFee,
66+
usd: usdFee,
67+
},
5968
resolver: async receipt => {
6069
const { logs } = receipt;
6170

src/types/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,11 @@ export enum PermissibleOperation {
394394
ModifyShareholderData = 'GTM_WHITELIST_UPDATE',
395395
}
396396

397+
export interface Fees {
398+
usd: BigNumber | null;
399+
poly: BigNumber;
400+
}
401+
397402
export interface Pojo {
398403
[key: string]:
399404
| string

0 commit comments

Comments
 (0)