Skip to content

Commit 97fce98

Browse files
committed
feat: add ticker availability check
1 parent a6df76a commit 97fce98

File tree

3 files changed

+95
-2
lines changed

3 files changed

+95
-2
lines changed

src/LowLevel/SecurityTokenRegistry.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import {
99
RegisterTickerArgs,
1010
GenerateSecurityTokenArgs,
1111
GetSecurityTokenArgs,
12+
GetTickerDetailsArgs,
13+
IsTickerAvailableArgs,
14+
TickerDetails,
1215
} from './types';
1316
import { fromWei } from './utils';
1417

@@ -19,6 +22,9 @@ interface SecurityTokenRegistryContract extends GenericContract {
1922
ticker: string,
2023
tokenName: string
2124
): TransactionObject<void>;
25+
getTickerDetails(
26+
ticker: string
27+
): TransactionObject<{ [key: string]: string }>;
2228
getTickerRegistrationFee(): TransactionObject<string>;
2329
getSecurityTokenLaunchFee(): TransactionObject<string>;
2430
getSecurityTokenAddress(ticker: string): TransactionObject<string>;
@@ -49,6 +55,68 @@ export class SecurityTokenRegistry extends Contract<
4955
.send({ from: this.context.account });
5056
};
5157

58+
public getTickerDetails = async ({ ticker }: GetTickerDetailsArgs) => {
59+
const keysMap: { [key: string]: string } = {
60+
'0': 'owner',
61+
'1': 'registrationDate',
62+
'2': 'expiryDate',
63+
'3': 'name',
64+
'4': 'status',
65+
};
66+
67+
const details = await this.contract.methods
68+
.getTickerDetails(ticker)
69+
.call({ from: this.context.account });
70+
71+
// Convert the object returned by SecurityTokenRegistry.getTickerDetails to a TickerDetails object.
72+
try {
73+
const initialValue = <TickerDetails>{
74+
owner: '0x0000000000000000000000000000000000000000',
75+
registrationDate: 0,
76+
expiryDate: 0,
77+
name: '',
78+
status: false,
79+
};
80+
const labeledDetails: TickerDetails = Object.keys(details).reduce(
81+
(acc, cur: string) => {
82+
let val: string | number = details[cur];
83+
// Parse unix timestamps.
84+
if (cur === '1' || cur === '2') {
85+
val = parseInt(val);
86+
}
87+
const newKey: string = keysMap[cur];
88+
acc[newKey] = val;
89+
return acc;
90+
},
91+
initialValue
92+
);
93+
94+
return labeledDetails;
95+
} catch (error) {
96+
throw new Error('Unexpected ticker details data.');
97+
}
98+
};
99+
100+
/**
101+
* While lacking a public, smart contract function to check for ticker availability, this function attempts to
102+
* immitate the internal function SecurityTokenRegistry._tickerAvailable()
103+
* @see https://github.com/PolymathNetwork/polymath-core/blob/aa635df01588f733ce95bc13fe319c7d3c858a24/contracts/SecurityTokenRegistry.sol#L318
104+
*/
105+
public isTickerAvailable = async ({
106+
ticker,
107+
}: IsTickerAvailableArgs): Promise<boolean> => {
108+
const details = await this.getTickerDetails({ ticker });
109+
110+
if (details.owner !== '0x0000000000000000000000000000000000000000') {
111+
if (Date.now() > details.expiryDate * 1000 && !details.status) {
112+
return true;
113+
}
114+
return false;
115+
}
116+
117+
return true;
118+
};
119+
52120
public generateSecurityToken = async ({
53121
tokenName,
54122
ticker,

src/LowLevel/types.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,23 @@ export interface GetSecurityTokenArgs {
229229
ticker: string;
230230
}
231231

232+
export interface GetTickerDetailsArgs {
233+
ticker: string;
234+
}
235+
236+
export interface IsTickerAvailableArgs {
237+
ticker: string;
238+
}
239+
240+
export interface TickerDetails {
241+
[key: string]: any;
242+
owner: string;
243+
registrationDate: number;
244+
expiryDate: number;
245+
name: string;
246+
status: boolean;
247+
}
248+
232249
export enum NetworkIds {
233250
Local = 15,
234251
LocalVm = 16,

src/procedures/ReserveSecurityToken.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,18 @@ export class ReserveSecurityToken extends Procedure<
3030
});
3131
}
3232

33-
// TODO @RafaelVidaurre: See if ticker is not already registered
33+
const isAvailable = await securityTokenRegistry.isTickerAvailable({
34+
ticker: symbol,
35+
});
36+
// @TODO remon-nashid perhaps we should display an error message rather than throwing?
37+
if (!isAvailable) {
38+
throw new PolymathError({
39+
message: `Ticker ${symbol} has already been registered`,
40+
code: ErrorCodes.ProcedureValidationError,
41+
});
42+
}
3443

3544
const fee = await securityTokenRegistry.getTickerRegistrationFee();
36-
3745
await this.addTransaction(Approve)({
3846
amount: fee,
3947
spender: securityTokenRegistry.address,

0 commit comments

Comments
 (0)