forked from starknet-io/starknet.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
uint256.ts
136 lines (121 loc) · 3.73 KB
/
uint256.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* eslint-disable no-bitwise */
/**
* Singular class handling cairo u256 data type
*/
import { BigNumberish, Uint256 } from '../../types';
import { addHexPrefix } from '../encode';
import { CairoFelt } from './felt';
export const UINT_128_MAX = (1n << 128n) - 1n;
export const UINT_256_MAX = (1n << 256n) - 1n;
export const UINT_256_MIN = 0n;
export const UINT_256_LOW_MAX = 340282366920938463463374607431768211455n;
export const UINT_256_HIGH_MAX = 340282366920938463463374607431768211455n;
export const UINT_256_LOW_MIN = 0n;
export const UINT_256_HIGH_MIN = 0n;
export class CairoUint256 {
public low: bigint;
public high: bigint;
static abiSelector = 'core::integer::u256';
/**
* Default constructor (Lib usage)
* @param bigNumberish BigNumberish value representing uin256
*/
public constructor(bigNumberish: BigNumberish);
/**
* Direct props initialization (Api response)
*/
public constructor(low: BigNumberish, high: BigNumberish);
/**
* Initialization from Uint256 object
*/
public constructor(uint256: Uint256);
public constructor(...arr: any[]) {
if (typeof arr[0] === 'object' && arr.length === 1 && 'low' in arr[0] && 'high' in arr[0]) {
const props = CairoUint256.validateProps(arr[0].low, arr[0].high);
this.low = props.low;
this.high = props.high;
} else if (arr.length === 1) {
const bigInt = CairoUint256.validate(arr[0]);
this.low = bigInt & UINT_128_MAX;
this.high = bigInt >> 128n;
} else if (arr.length === 2) {
const props = CairoUint256.validateProps(arr[0], arr[1]);
this.low = props.low;
this.high = props.high;
} else {
throw Error('Incorrect constructor parameters');
}
}
/**
* Validate if BigNumberish can be represented as Unit256
*/
static validate(bigNumberish: BigNumberish) {
const bigInt = BigInt(bigNumberish);
if (bigInt < UINT_256_MIN) throw Error('bigNumberish is smaller than UINT_256_MIN');
if (bigInt > UINT_256_MAX) throw new Error('bigNumberish is bigger than UINT_256_MAX');
return bigInt;
}
/**
* Validate if low and high can be represented as Unit256
*/
static validateProps(low: BigNumberish, high: BigNumberish) {
const bigIntLow = BigInt(low);
const bigIntHigh = BigInt(high);
if (bigIntLow < UINT_256_LOW_MIN || bigIntLow > UINT_256_LOW_MAX) {
throw new Error('low is out of range UINT_256_LOW_MIN - UINT_256_LOW_MAX');
}
if (bigIntHigh < UINT_256_HIGH_MIN || bigIntHigh > UINT_256_HIGH_MAX) {
throw new Error('high is out of range UINT_256_HIGH_MIN - UINT_256_HIGH_MAX');
}
return { low: bigIntLow, high: bigIntHigh };
}
/**
* Check if BigNumberish can be represented as Unit256
*/
static is(bigNumberish: BigNumberish) {
try {
CairoUint256.validate(bigNumberish);
} catch (error) {
return false;
}
return true;
}
/**
* Check if provided abi type is this data type
*/
static isAbiType(abiType: string) {
return abiType === CairoUint256.abiSelector;
}
/**
* Return bigint representation
*/
toBigInt() {
return (this.high << 128n) + this.low;
}
/**
* Return Uint256 structure with HexString props
* {low: HexString, high: HexString}
*/
toUint256HexString() {
return {
low: addHexPrefix(this.low.toString(16)),
high: addHexPrefix(this.high.toString(16)),
};
}
/**
* Return Uint256 structure with DecimalString props
* {low: DecString, high: DecString}
*/
toUint256DecimalString() {
return {
low: this.low.toString(10),
high: this.high.toString(10),
};
}
/**
* Return api requests representation witch is felt array
*/
toApiRequest() {
return [CairoFelt(this.low), CairoFelt(this.high)];
}
}