Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions __tests__/utils/shortString.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { decodeShortString, encodeShortString } from '../../src/utils/shortString';

describe('shortString', () => {
test('should convert string to number', () => {
expect(encodeShortString('hello')).toMatchInlineSnapshot(`"0x68656c6c6f"`);
});
test('should convert number to string', () => {
expect(decodeShortString('0x68656c6c6f')).toMatchInlineSnapshot(`"hello"`);
});
test('should throw if string is too long', () => {
expect(() =>
encodeShortString('hello world hello world hello world hello world hello world hello world')
).toThrowErrorMatchingInlineSnapshot(
`"hello world hello world hello world hello world hello world hello world is too long"`
);
});
test('should throw if string contains non ascii chars', () => {
expect(() => encodeShortString('hello\uD83D\uDE00')).toThrowErrorMatchingInlineSnapshot(
`"hello😀 is not an ASCII string"`
);
});
});
32 changes: 32 additions & 0 deletions __tests__/utils/uint256.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ONE } from '../../src/constants';
import { toBN } from '../../src/utils/number';
import { UINT_128_MAX, UINT_256_MAX, bnToUint256, uint256ToBN } from '../../src/utils/uint256';

describe('cairo uint256', () => {
test('should convert 0 from BN to uint256 struct', () => {
const uint256 = bnToUint256('0');
expect(uint256).toMatchInlineSnapshot(`
Object {
"high": "0x0",
"low": "0x0",
}
`);
});
test('should convert 0 from uint256 to BN', () => {
expect(uint256ToBN({ low: '0x0', high: '0x0' }).toString()).toMatchInlineSnapshot(`"0"`);
});
test('should convert BN over 2^128 to uint256 struct', () => {
const uint256 = bnToUint256(UINT_128_MAX.add(ONE));
expect(uint256).toMatchInlineSnapshot(`
Object {
"high": "0x1",
"low": "0x0",
}
`);
});
test('should throw if BN over uint256 range', () => {
expect(() => bnToUint256(UINT_256_MAX.add(toBN(1)))).toThrowErrorMatchingInlineSnapshot(
`"Number is too large"`
);
});
});
10 changes: 4 additions & 6 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import BN from 'bn.js';

import { toBN } from './utils/number';

export { IS_BROWSER } from './utils/encode';

export const ZERO: BN = toBN(0);
export const ONE: BN = toBN(1);
export const TWO: BN = toBN(2);
export const MASK_250: BN = TWO.pow(toBN(250)).sub(ONE); // 2 ** 250 - 1
export const ZERO = toBN(0);
export const ONE = toBN(1);
export const TWO = toBN(2);
export const MASK_250 = TWO.pow(toBN(250)).sub(ONE); // 2 ** 250 - 1

/**
* The following is taken from https://github.com/starkware-libs/starkex-resources/blob/master/crypto/starkware/crypto/signature/pedersen_params.json but converted to hex, because JS is very bad handling big integers by default
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ export * as json from './utils/json';
export * as number from './utils/number';
export * as stark from './utils/stark';
export * as ec from './utils/ellipticCurve';
export * as uint256 from './utils/uint256';
export * as shortString from './utils/shortString';
21 changes: 21 additions & 0 deletions src/utils/shortString.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { addHexPrefix, removeHexPrefix } from './encode';

export function isASCII(str: string) {
// eslint-disable-next-line no-control-regex
return /^[\x00-\x7F]*$/.test(str);
}

// function to check if string has less or equal 31 characters
export function isShortString(str: string) {
return str.length <= 31;
}

export function encodeShortString(str: string) {
if (!isASCII(str)) throw new Error(`${str} is not an ASCII string`);
if (!isShortString(str)) throw new Error(`${str} is too long`);
return addHexPrefix(str.replace(/./g, (char) => char.charCodeAt(0).toString(16)));
}

export function decodeShortString(str: string) {
return removeHexPrefix(str).replace(/.{2}/g, (hex) => String.fromCharCode(parseInt(hex, 16)));
}
4 changes: 4 additions & 0 deletions src/utils/stark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,7 @@ export function formatSignature(sig?: [BigNumberish, BigNumberish]): [string, st
return [];
}
}

export function compileStructToCalldata<S extends { [k: string]: string }>(struct: S): string[] {
return Object.values(struct);
}
32 changes: 32 additions & 0 deletions src/utils/uint256.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { addHexPrefix } from './encode';
import { BigNumberish, toBN } from './number';

// Represents an integer in the range [0, 2^256).
export interface Uint256 {
// The low 128 bits of the value.
low: BigNumberish;
// The high 128 bits of the value.
high: BigNumberish;
}

// function to convert Uint256 to BN
export function uint256ToBN(uint256: Uint256) {
return toBN(uint256.high).shln(128).add(toBN(uint256.low));
}

export const UINT_128_MAX = toBN(1).shln(128).sub(toBN(1));
export const UINT_256_MAX = toBN(1).shln(256).sub(toBN(1));
// function to check if BN is smaller or equal 2**256-1
export function isUint256(bn: BigNumberish): boolean {
return toBN(bn).lte(UINT_256_MAX);
}

// function to convert BN to Uint256
export function bnToUint256(bignumber: BigNumberish): Uint256 {
const bn = toBN(bignumber);
if (!isUint256(bn)) throw new Error('Number is too large');
return {
low: addHexPrefix(bn.maskn(128).toString(16)),
high: addHexPrefix(bn.shrn(128).toString(16)),
};
}