Skip to content

Commit d6ec0ca

Browse files
feat: 🎸 validate new ticker length against live chain TickerConfig
1 parent 3ecab6b commit d6ec0ca

5 files changed

Lines changed: 85 additions & 1 deletion

File tree

src/api/procedures/createAsset.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import {
4242
stringToTicker,
4343
} from '~/utils/conversion';
4444
import {
45+
assertTickerLengthValid,
4546
checkTxType,
4647
isAllowedCharacters,
4748
optionize,
@@ -272,6 +273,7 @@ export async function prepareCreateAsset(
272273
let rawTicker: PolymeshPrimitivesTicker | undefined;
273274

274275
if (ticker) {
276+
await assertTickerLengthValid(ticker, context);
275277
rawTicker = stringToTicker(ticker, context);
276278
}
277279

src/api/procedures/createNftCollection.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import {
4545
stringToTicker,
4646
} from '~/utils/conversion';
4747
import {
48+
assertTickerLengthValid,
4849
checkTxType,
4950
isAllowedCharacters,
5051
optionize,
@@ -190,6 +191,7 @@ export async function prepareCreateNftCollection(
190191

191192
if (ticker) {
192193
assertTickerOk(ticker);
194+
await assertTickerLengthValid(ticker, context);
193195
}
194196

195197
const internalNftType = getInternalNftType(customTypeData, nftType);

src/api/procedures/reserveTicker.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Context, PolymeshError, Procedure, TickerReservation } from '~/internal
44
import { ErrorCode, ReserveTickerParams, RoleType, TickerReservationStatus, TxTags } from '~/types';
55
import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal';
66
import { stringToTicker, tickerToString } from '~/utils/conversion';
7-
import { filterEventRecords, isAllowedCharacters } from '~/utils/internal';
7+
import { assertTickerLengthValid, filterEventRecords, isAllowedCharacters } from '~/utils/internal';
88

99
/**
1010
* @hidden
@@ -43,6 +43,8 @@ export async function prepareReserveTicker(
4343
});
4444
}
4545

46+
await assertTickerLengthValid(ticker, context);
47+
4648
const rawTicker = stringToTicker(ticker, context);
4749

4850
const reservation = new TickerReservation({ ticker }, context);

src/utils/__tests__/internal.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import {
9898
assertMetaLength,
9999
assertNoPendingAuthorizationExists,
100100
assertStatIsSet,
101+
assertTickerLengthValid,
101102
assertTickerValid,
102103
calculateNextKey,
103104
calculateRawStakingPayee,
@@ -1792,6 +1793,52 @@ describe('assertTickerValid', () => {
17921793
});
17931794
});
17941795

1796+
describe('assertTickerLengthValid', () => {
1797+
it('should throw an error if the ticker length exceeds the chain configured max ticker length', async () => {
1798+
const context = dsMockUtils.getContextInstance();
1799+
const maxTickerLength = new BigNumber(6);
1800+
1801+
dsMockUtils.createQueryMock('asset', 'tickerConfig', {
1802+
returnValue: dsMockUtils.createMockTickerRegistrationConfig({
1803+
maxTickerLength: dsMockUtils.createMockU8(maxTickerLength),
1804+
registrationLength: dsMockUtils.createMockOption(),
1805+
}),
1806+
});
1807+
1808+
await expect(assertTickerLengthValid('TOO_LONG', context)).rejects.toThrow(
1809+
`Ticker length must be between 1 and ${maxTickerLength.toString()} characters`
1810+
);
1811+
});
1812+
1813+
it('should throw an error if the ticker is empty', async () => {
1814+
const context = dsMockUtils.getContextInstance();
1815+
1816+
dsMockUtils.createQueryMock('asset', 'tickerConfig', {
1817+
returnValue: dsMockUtils.createMockTickerRegistrationConfig({
1818+
maxTickerLength: dsMockUtils.createMockU8(new BigNumber(12)),
1819+
registrationLength: dsMockUtils.createMockOption(),
1820+
}),
1821+
});
1822+
1823+
await expect(assertTickerLengthValid('', context)).rejects.toThrow(
1824+
'Ticker length must be between 1 and 12 characters'
1825+
);
1826+
});
1827+
1828+
it('should not throw an error if the ticker length is within the chain configured max ticker length', async () => {
1829+
const context = dsMockUtils.getContextInstance();
1830+
1831+
dsMockUtils.createQueryMock('asset', 'tickerConfig', {
1832+
returnValue: dsMockUtils.createMockTickerRegistrationConfig({
1833+
maxTickerLength: dsMockUtils.createMockU8(new BigNumber(12)),
1834+
registrationLength: dsMockUtils.createMockOption(),
1835+
}),
1836+
});
1837+
1838+
await expect(assertTickerLengthValid('FAKE_TICKER', context)).resolves.not.toThrow();
1839+
});
1840+
});
1841+
17951842
describe('neededStatTypeForRestrictionInput', () => {
17961843
beforeAll(() => {
17971844
dsMockUtils.initMocks();

src/utils/internal.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ import {
134134
stringToTicker,
135135
tickerToString,
136136
transferRestrictionTypeToStatOpType,
137+
u8ToBigNumber,
137138
u32ToBigNumber,
138139
u64ToBigNumber,
139140
} from '~/utils/conversion';
@@ -1001,6 +1002,36 @@ export function assertTickerValid(ticker: string): void {
10011002
}
10021003
}
10031004

1005+
/**
1006+
* @hidden
1007+
*
1008+
* Validates a ticker's length against the chain's current ticker registration rules.
1009+
*
1010+
* @note this is distinct from {@link assertTickerValid}, which enforces the fixed 12 byte
1011+
* width of the on chain `Ticker` type. `maxTickerLength` is a separate, governance
1012+
* configurable ceiling (never greater than 12) used to validate new ticker registrations
1013+
*/
1014+
export async function assertTickerLengthValid(ticker: string, context: Context): Promise<void> {
1015+
const {
1016+
polymeshApi: {
1017+
query: {
1018+
asset: { tickerConfig },
1019+
},
1020+
},
1021+
} = context;
1022+
1023+
const { maxTickerLength: rawMaxTickerLength } = await tickerConfig();
1024+
const maxTickerLength = u8ToBigNumber(rawMaxTickerLength);
1025+
1026+
if (!ticker.length || maxTickerLength.lt(ticker.length)) {
1027+
throw new PolymeshError({
1028+
code: ErrorCode.ValidationError,
1029+
message: `Ticker length must be between 1 and ${maxTickerLength.toString()} characters`,
1030+
data: { maxTickerLength },
1031+
});
1032+
}
1033+
}
1034+
10041035
/**
10051036
* @hidden
10061037
*/

0 commit comments

Comments
 (0)