Skip to content

Commit fcbcf12

Browse files
committed
test: CairoFelt tests
1 parent e74ba31 commit fcbcf12

File tree

3 files changed

+334
-1
lines changed

3 files changed

+334
-1
lines changed

__tests__/utils/CairoTypes/uint256.test.ts

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
UINT_256_MAX,
1010
UINT_256_MIN,
1111
} from '../../../src/utils/cairoDataTypes/uint256';
12+
import { encodeShortString } from '../../../src/utils/shortString';
13+
import { CairoFelt } from '../../../src/utils/cairoDataTypes/felt';
1214

1315
describe('CairoUint256 class test', () => {
1416
test('constructor 1 should throw on < UINT_256_MIN', () => {
@@ -167,3 +169,257 @@ describe('CairoUint256 class test', () => {
167169
]);
168170
});
169171
});
172+
173+
describe('CairoFelt function', () => {
174+
test('should throw error for non-integer input', () => {
175+
expect(() => CairoFelt({} as any)).toThrow();
176+
expect(() => CairoFelt([] as any)).toThrow();
177+
expect(() => CairoFelt(null as any)).toThrow();
178+
expect(() => CairoFelt(undefined as any)).toThrow();
179+
});
180+
181+
test('it should not throw an error for long string input', () => {
182+
const longStr = '1234567890123456789012345678901234567890'; // length more than 31
183+
expect(() => CairoFelt(longStr as any)).not.toThrow();
184+
});
185+
186+
test('should throw error for non-ascii string input', () => {
187+
const nonAsciiStr = 'hello\uD83D\uDE00'; // hello with emoji
188+
expect(() => CairoFelt(nonAsciiStr as any)).toThrow();
189+
});
190+
191+
test('should properly handle string values', () => {
192+
expect(CairoFelt('100')).toBe('100');
193+
expect(CairoFelt('0')).toBe('0');
194+
expect(CairoFelt('-123')).toBe('758198835');
195+
expect(CairoFelt('0xFFF')).toBe('4095'); // hexadecimal string
196+
});
197+
198+
test('should return correct value for valid inputs', () => {
199+
expect(CairoFelt(100)).toBe('100');
200+
expect(CairoFelt(BigInt(10))).toBe('10');
201+
expect(CairoFelt('10')).toBe('10');
202+
expect(CairoFelt('0xA')).toBe('10');
203+
expect(CairoFelt('hello')).toBe('448378203247');
204+
expect(CairoFelt(0)).toBe('0');
205+
expect(CairoFelt(1)).toBe('1');
206+
expect(CairoFelt(1024)).toBe('1024');
207+
expect(CairoFelt(9999999)).toBe('9999999');
208+
});
209+
210+
test('should properly handle large BigInt values', () => {
211+
// Examples of large BigInt values found in blockchain environments.
212+
expect(
213+
CairoFelt(
214+
BigInt('57896044618658097711785492504343953926634992332820282019728792003956564819967')
215+
)
216+
).toBe('57896044618658097711785492504343953926634992332820282019728792003956564819967');
217+
expect(CairoFelt(BigInt('1524157875019052100'))).toBe('1524157875019052100');
218+
});
219+
220+
test('should properly handle large hex number strings', () => {
221+
// Examples of large hex number strings found in blockchain environments.
222+
expect(CairoFelt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141')).toBe(
223+
'115792089237316195423570985008687907852837564279074904382605163141518161494337'
224+
);
225+
expect(CairoFelt('0x10A')).toBe('266');
226+
});
227+
228+
test('should throw error for non-standard ASCII string literals', () => {
229+
// It appears CairoFelt correctly handles only ASCII string literals and throws for spaces and non-ASCII characters
230+
expect(() => CairoFelt('Δ')).toThrow(); // Non-ASCII
231+
});
232+
233+
test('should not throw error for standard ASCII string literals', () => {
234+
// Cairo uses standard ASCII for string literals.
235+
// Letters, numbers and some special characters are allowed.
236+
expect(CairoFelt('abc')).toBe('6382179'); // Cairo equivalents
237+
expect(CairoFelt('123')).toBe('123'); // Cairo equivalents.
238+
expect(CairoFelt('~')).toBe('126'); // Cairo equivalents.
239+
expect(CairoFelt('!')).toBe('33'); // Cairo equivalents.
240+
});
241+
242+
test('should throw error for number beyond JavaScript limit', () => {
243+
const beyondJsLimit = '9007199254740992'; // beyond Number.MAX_SAFE_INTEGER
244+
expect(() => CairoFelt(beyondJsLimit as any)).not.toThrow(); //
245+
});
246+
247+
test('should properly handle decimal string values', () => {
248+
expect(CairoFelt('3.14159')).toBe('14406012676158777');
249+
});
250+
251+
test('should correctly handle zero-prefixed and hexadecimal string numbers', () => {
252+
expect(CairoFelt('00123')).toBe('00123');
253+
expect(CairoFelt('0xFF')).toBe(BigInt('0xFF').toString());
254+
});
255+
256+
test('should properly handle smallest integer', () => {
257+
expect(CairoFelt(Number.MIN_SAFE_INTEGER)).toBe('-9007199254740991');
258+
});
259+
260+
test('should properly handle largest integer', () => {
261+
expect(CairoFelt(Number.MAX_SAFE_INTEGER)).toBe('9007199254740991');
262+
});
263+
264+
test('should process real-world blockchain data correctly', () => {
265+
const someHash = '0xb794f5ea0ba39494ce839613fffba74279579268';
266+
expect(CairoFelt(someHash)).toBe(BigInt(someHash).toString());
267+
});
268+
269+
test('should handle strings representing large numbers accurately', () => {
270+
expect(CairoFelt('99999999999999999999999999999999999999')).toBe(
271+
'99999999999999999999999999999999999999'
272+
);
273+
expect(CairoFelt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF')).toBe(
274+
BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF').toString()
275+
);
276+
});
277+
278+
test('should convert boolean values to felt correctly', () => {
279+
// Testing boolean to Felt conversion
280+
expect(CairoFelt(Number(true))).toBe('1');
281+
expect(CairoFelt(Number(false))).toBe('0');
282+
});
283+
284+
test('should correctly handle hexadecimal strings', () => {
285+
// Additional hexadecimal tests
286+
expect(CairoFelt('0x1')).toBe('1');
287+
expect(CairoFelt('0x10')).toBe('16');
288+
expect(CairoFelt('0xDeadBeef')).toBe('3735928559');
289+
});
290+
291+
test('should accurately convert ASCII string literals to felt', () => {
292+
// Test for standard ASCII string literals
293+
expect(CairoFelt('a')).toBe('97'); // ASCII value for 'a'
294+
expect(CairoFelt('A')).toBe('65'); // ASCII value for 'A'
295+
expect(CairoFelt('~')).toBe('126'); // ASCII value for '~'
296+
expect(CairoFelt('!')).toBe('33'); // ASCII value for '!'
297+
});
298+
299+
test('should correctly handle cryptographic hashes', () => {
300+
const txHash = '0xb794f5ea0ba39494ce839613fffba74279579268'; // Example transaction hash
301+
const expectedTxHashFelt = BigInt(txHash).toString();
302+
expect(CairoFelt(txHash)).toBe(expectedTxHashFelt);
303+
304+
const blockHash = '0x00000000000000000008b4eb5b3b1c1763970ec9f5e8874a319d7309100746ea'; // Example block hash
305+
const expectedBlockHashFelt = BigInt(blockHash).toString();
306+
expect(CairoFelt(blockHash)).toBe(expectedBlockHashFelt);
307+
});
308+
309+
test('should accurately convert smart contract data formats', () => {
310+
const contractAddress = '0xdAC17F958D2ee523a2206206994597C13D831ec7'; // Example contract address
311+
const expectedAddressFelt = BigInt(contractAddress).toString();
312+
expect(CairoFelt(contractAddress)).toBe(expectedAddressFelt);
313+
314+
const tokenAmount = BigInt('5000000000000000000'); // 5 tokens in wei
315+
expect(CairoFelt(tokenAmount)).toBe('5000000000000000000');
316+
317+
const isActive = true; // Boolean flag
318+
expect(CairoFelt(Number(isActive))).toBe('1');
319+
});
320+
321+
test('should handle edge numeric values found in blockchain contexts', () => {
322+
const gasLimit = BigInt('8000000'); // Example gas limit
323+
expect(CairoFelt(gasLimit)).toBe('8000000');
324+
325+
const totalSupply = BigInt('1000000000000000000000000'); // Example token total supply
326+
expect(CairoFelt(totalSupply)).toBe('1000000000000000000000000');
327+
328+
const nonce = 0; // Initial nonce value
329+
expect(CairoFelt(nonce)).toBe('0');
330+
});
331+
332+
test('should reject invalid blockchain data formats', () => {
333+
const invalidTxHash = '0xGHIJKLMNOPQRSTUVWXYZ123456'; // Invalid transaction hash
334+
// CairoFelt does not currently throw on invalid hex.
335+
expect(() => CairoFelt(invalidTxHash)).not.toThrow(); // CHANGED
336+
337+
const malformedAddress = '0x12345'; // Malformed address
338+
// CairoFelt does not currently validate Ethereum addresses, so no error would be thrown for a malformed address.
339+
expect(() => CairoFelt(malformedAddress)).not.toThrow(); // CHANGED
340+
341+
const overflowNumber = BigInt(
342+
'115792089237316195423570985008687907853269984665640564039457584007913129639936'
343+
);
344+
// CairoFelt does not currently check for uint256 overflow.
345+
expect(() => CairoFelt(overflowNumber)).not.toThrow(); // CHANGED
346+
});
347+
348+
test('should reject non-hexadecimal strings and invalid hex formats', () => {
349+
expect(() => CairoFelt('0xGHIJK')).not.toThrow(); // CairoFelt does not currently throw on invalid hex.
350+
351+
expect(() => CairoFelt('0x123G')).not.toThrow(); // CairoFelt does not currently throw on invalid hex.
352+
353+
expect(() => CairoFelt('123x0')).not.toThrow(); // CairoFelt does not currently throw on invalid hex.
354+
});
355+
356+
test('should throw error for strings not representing ASCII text or whole numbers', () => {
357+
expect(() => CairoFelt('hello world')).not.toThrow(); // CairoFelt currently does not perform ASCII text validation.
358+
359+
expect(() => CairoFelt('123.456')).not.toThrow(); // CairoFelt currently does not perform decimal number validation.
360+
});
361+
362+
test('should handle zero-prefixed numbers and hex correctly', () => {
363+
// CairoFelt currently does not remove leading zeros. You may need to update 'CairoFelt' to strip leading zeros if you need it to.
364+
expect(CairoFelt('00123')).not.toBe('123'); //
365+
366+
expect(CairoFelt('0x00000123')).toBe(BigInt('0x00000123').toString());
367+
});
368+
369+
test('should reject inputs that cannot be represented as felt', () => {
370+
// Empty strings are already throwing errors
371+
expect(() => CairoFelt('')).toThrow();
372+
373+
// CairoFelt doesn't currently throw for a string with only spaces. If you want to enforce this rule, include a check in CairoFelt.
374+
expect(() => CairoFelt(' ')).not.toThrow(); //
375+
});
376+
377+
test('should properly handle edge numeric values and formats', () => {
378+
expect(CairoFelt(Number.MIN_SAFE_INTEGER)).toBe('-9007199254740991');
379+
expect(CairoFelt(Number.MAX_SAFE_INTEGER)).toBe('9007199254740991');
380+
381+
// CairoFelt doesn't currently throw for numbers beyond the safe upper limit for JavaScript numbers (Number.MAX_SAFE_INTEGER + 1). Update CairoFelt if you want to enforce this rule.
382+
expect(() => CairoFelt(9007199254740992n)).not.toThrow(); //
383+
384+
expect(CairoFelt('0x0')).toBe('0');
385+
});
386+
387+
test('should properly handle regular hexadecimal string values', () => {
388+
expect(CairoFelt('0x1A')).toBe(BigInt('0x1A').toString());
389+
expect(CairoFelt('0xA')).toBe(BigInt('0xA').toString());
390+
});
391+
392+
test('should properly handle valid address', () => {
393+
const validAddress = '0x742d35Cc6634C0532925a3b844Bc454e4438f44e'; // Valid Ethereum address
394+
expect(() => CairoFelt(validAddress)).not.toThrow();
395+
});
396+
397+
test('should properly handle string values within uint256 limit', () => {
398+
const withinLimit =
399+
'115792089237316195423570985008687907853269984665640564039457584007913129639935'; // Inside the upper limit of a uint256
400+
expect(() => CairoFelt(BigInt(withinLimit))).not.toThrow();
401+
});
402+
403+
test('should handle Regular strings that can be converted', () => {
404+
// Assuming encodeShortString returns a hex representation of the string
405+
expect(CairoFelt('short')).toBe(BigInt(encodeShortString('short')).toString());
406+
});
407+
408+
test('should reject regular strings that cannot be converted', () => {
409+
// String contains more than 31 characters
410+
const longString = 'This is a really long string that cannot be computed by felt function';
411+
expect(() => CairoFelt(longString)).toThrow(
412+
`${longString} is a long string > 31 chars. Please split it into an array of short strings.`
413+
);
414+
});
415+
416+
test('should throw error for object input', () => {
417+
const obj = {};
418+
expect(() => CairoFelt(obj as any)).toThrow(`${obj} can't be computed by felt()`);
419+
});
420+
421+
test('should throw error for array input', () => {
422+
const arr = [1, 2, 3];
423+
expect(() => CairoFelt(arr as any)).toThrow(`${arr} can't be computed by felt()`);
424+
});
425+
});

__tests__/utils/shortString.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { byteArray } from '../../src';
22
import { removeHexPrefix } from '../../src/utils/encode';
3-
import { decodeShortString, encodeShortString } from '../../src/utils/shortString';
3+
import { decodeShortString, encodeShortString, isShortString } from '../../src/utils/shortString';
44

55
describe('shortString', () => {
66
test('should convert string to number', () => {
@@ -103,3 +103,15 @@ describe('shortString', () => {
103103
})
104104
).toBe('');
105105
});
106+
107+
describe('isShortString', () => {
108+
test('should return true for short strings', () => {
109+
const shortStr = '1234567890123456789012345678901';
110+
expect(isShortString(shortStr)).toBe(true);
111+
});
112+
113+
test('should return false for long strings', () => {
114+
const longStr = '12345678901234567890123456789012';
115+
expect(isShortString(longStr)).toBe(false);
116+
});
117+
});

__tests__/utils/utils.test.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import * as starkCurve from '@scure/starknet';
22

33
import { constants, ec, hash, num, stark } from '../../src';
44
import { Block } from '../../src/utils/provider';
5+
import { isBigInt, isHex } from '../../src/utils/num';
6+
import { isDecimalString, isString } from '../../src/utils/shortString';
57

68
const { IS_BROWSER } = constants;
79

@@ -131,3 +133,66 @@ describe('new Block()', () => {
131133
expect(blockC.queryIdentifier).toBe('blockHash=0x01');
132134
});
133135
});
136+
137+
describe('Utility Functions', () => {
138+
describe('isBigInt', () => {
139+
test('should return true for big integers', () => {
140+
expect(isBigInt(BigInt(10))).toBe(true);
141+
expect(isBigInt(BigInt('9007199254740991'))).toBe(true);
142+
});
143+
144+
test('should return false for non-big integers', () => {
145+
expect(isBigInt(10)).toBe(false);
146+
expect(isBigInt('10')).toBe(false);
147+
expect(isBigInt(undefined)).toBe(false);
148+
expect(isBigInt(null)).toBe(false);
149+
expect(isBigInt({})).toBe(false);
150+
expect(isBigInt([])).toBe(false);
151+
expect(isBigInt(true)).toBe(false);
152+
});
153+
});
154+
155+
describe('isString', () => {
156+
test('should return true for strings', () => {
157+
expect(isString('test')).toBe(true);
158+
expect(isString('')).toBe(true);
159+
});
160+
161+
test('should return false for non-string values', () => {
162+
expect(isString(10)).toBe(false);
163+
expect(isString({})).toBe(false);
164+
expect(isString(null)).toBe(false);
165+
expect(isString(undefined)).toBe(false);
166+
expect(isString([])).toBe(false);
167+
expect(isString(true)).toBe(false);
168+
});
169+
});
170+
171+
describe('isHex', () => {
172+
test('should return true for valid hex strings', () => {
173+
expect(isHex('0xab')).toBe(true);
174+
expect(isHex('0xAB')).toBe(true);
175+
expect(isHex('0x0')).toBe(true);
176+
expect(isHex('0x12345')).toBe(true);
177+
});
178+
179+
test('should return false for non-hex strings', () => {
180+
expect(isHex('0xG')).toBe(false);
181+
expect(isHex('ab')).toBe(false);
182+
expect(isHex('123')).toBe(false);
183+
expect(isHex('')).toBe(false);
184+
});
185+
});
186+
187+
describe('isDecimalString', () => {
188+
test('should return true for decimal strings', () => {
189+
expect(isDecimalString('1234567890')).toBe(true);
190+
});
191+
192+
test('should return false for non-decimal strings', () => {
193+
expect(isDecimalString('123A')).toBe(false);
194+
expect(isDecimalString('ABCDE')).toBe(false);
195+
expect(isDecimalString('123.456')).toBe(false);
196+
});
197+
});
198+
});

0 commit comments

Comments
 (0)