Skip to content

Commit f6e3e60

Browse files
authored
Create cairo.ts
1 parent e9baaa8 commit f6e3e60

File tree

1 file changed

+279
-0
lines changed

1 file changed

+279
-0
lines changed

src/utils/calldata/enum/cairo.ts

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
import {
2+
Abi,
3+
AbiEnums,
4+
AbiStructs,
5+
BigNumberish,
6+
ContractVersion,
7+
ETH_ADDRESS,
8+
Literal,
9+
NON_ZERO_PREFIX,
10+
Uint,
11+
Uint256,
12+
Uint512,
13+
} from '../../types';
14+
import { CairoFelt } from '../cairoDataTypes/felt';
15+
import { CairoUint256 } from '../cairoDataTypes/uint256';
16+
import { CairoUint512 } from '../cairoDataTypes/uint512';
17+
18+
// Intended for internal usage, maybe should be exported somewhere else and not exported to utils
19+
/**
20+
* Checks if the given name ends with "_len".
21+
*
22+
* @param {string} name - The name to be checked.
23+
* @returns - True if the name ends with "_len", false otherwise.
24+
*/
25+
export const isLen = (name: string) => /_len$/.test(name);
26+
/**
27+
* Checks if a given type is felt.
28+
*
29+
* @param {string} type - The type to check.
30+
* @returns - True if the type is felt, false otherwise.
31+
*/
32+
export const isTypeFelt = (type: string) => type === 'felt' || type === 'core::felt252';
33+
/**
34+
* Checks if the given type is an array type.
35+
*
36+
* @param {string} type - The type to check.
37+
* @returns - `true` if the type is an array type, `false` otherwise.
38+
*/
39+
export const isTypeArray = (type: string) =>
40+
/\*/.test(type) ||
41+
type.startsWith('core::array::Array::') ||
42+
type.startsWith('core::array::Span::');
43+
44+
/**
45+
* Checks if the given type is a tuple type.
46+
*
47+
* @param {string} type - The type to be checked.
48+
* @returns - `true` if the type is a tuple type, otherwise `false`.
49+
*/
50+
export const isTypeTuple = (type: string) => /^\(.*\)$/i.test(type);
51+
/**
52+
* Checks whether a given type is a named tuple.
53+
*
54+
* @param {string} type - The type to be checked.
55+
* @returns - True if the type is a named tuple, false otherwise.
56+
*/
57+
export const isTypeNamedTuple = (type: string) => /\(.*\)/i.test(type) && type.includes(':');
58+
/**
59+
* Checks if a given type is a struct.
60+
*
61+
* @param {string} type - The type to check for existence.
62+
* @param {AbiStructs} structs - The collection of structs to search in.
63+
* @returns - True if the type exists in the structs, false otherwise.
64+
*/
65+
export const isTypeStruct = (type: string, structs: AbiStructs) => type in structs;
66+
/**
67+
* Checks if a given type is an enum.
68+
*
69+
* @param {string} type - The type to check.
70+
* @param {AbiEnums} enums - The enumeration to search in.
71+
* @returns - True if the type exists in the enumeration, otherwise false.
72+
*/
73+
export const isTypeEnum = (type: string, enums: AbiEnums) => type in enums;
74+
/**
75+
* Determines if the given type is an Option type.
76+
*
77+
* @param {string} type - The type to check.
78+
* @returns - True if the type is an Option type, false otherwise.
79+
*/
80+
export const isTypeOption = (type: string) => type.startsWith('core::option::Option::');
81+
/**
82+
* Checks whether a given type starts with 'core::result::Result::'.
83+
*
84+
* @param {string} type - The type to check.
85+
* @returns - True if the type starts with 'core::result::Result::', false otherwise.
86+
*/
87+
export const isTypeResult = (type: string) => type.startsWith('core::result::Result::');
88+
/**
89+
* Checks if the given value is a valid Uint type.
90+
*
91+
* @param {string} type - The value to check.
92+
* @returns - Returns true if the value is a valid Uint type, otherwise false.
93+
*/
94+
export const isTypeUint = (type: string) => Object.values(Uint).includes(type as Uint);
95+
// Legacy Export
96+
/**
97+
* Checks if the given type is `uint256`.
98+
*
99+
* @param {string} type - The type to be checked.
100+
* @returns - Returns true if the type is `uint256`, otherwise false.
101+
*/
102+
export const isTypeUint256 = (type: string) => CairoUint256.isAbiType(type);
103+
/**
104+
* Checks if the given type is a literal type.
105+
*
106+
* @param {string} type - The type to check.
107+
* @returns - True if the type is a literal type, false otherwise.
108+
*/
109+
export const isTypeLiteral = (type: string) => Object.values(Literal).includes(type as Literal);
110+
/**
111+
* Checks if the given type is a boolean type.
112+
*
113+
* @param {string} type - The type to be checked.
114+
* @returns - Returns true if the type is a boolean type, otherwise false.
115+
*/
116+
export const isTypeBool = (type: string) => type === 'core::bool';
117+
/**
118+
* Checks if the provided type is equal to 'core::starknet::contract_address::ContractAddress'.
119+
* @param {string} type - The type to be checked.
120+
* @returns - true if the type matches 'core::starknet::contract_address::ContractAddress', false otherwise.
121+
*/
122+
export const isTypeContractAddress = (type: string) => type === Literal.ContractAddress;
123+
/**
124+
* Determines if the given type is an Ethereum address type.
125+
*
126+
* @param {string} type - The type to check.
127+
* @returns - Returns true if the given type is 'core::starknet::eth_address::EthAddress', otherwise false.
128+
*/
129+
export const isTypeEthAddress = (type: string) => type === ETH_ADDRESS;
130+
/**
131+
* Checks if the given type is 'core::bytes_31::bytes31'.
132+
*
133+
* @param {string} type - The type to check.
134+
* @returns - True if the type is 'core::bytes_31::bytes31', false otherwise.
135+
*/
136+
export const isTypeBytes31 = (type: string) => type === 'core::bytes_31::bytes31';
137+
/**
138+
* Checks if the given type is equal to the 'core::byte_array::ByteArray'.
139+
*
140+
* @param {string} type - The type to check.
141+
* @returns - True if the given type is equal to 'core::byte_array::ByteArray', false otherwise.
142+
*/
143+
export const isTypeByteArray = (type: string) => type === 'core::byte_array::ByteArray';
144+
145+
/**
146+
* Checks if the given type is equal to the u96 type
147+
*
148+
* @param {string} type - The type to check.
149+
* @returns - True if the given type is equal to u96, false otherwise.
150+
*/
151+
export const isTypeU96 = (type: string) =>
152+
type === 'core::internal::bounded_int::BoundedInt::<0, 79228162514264337593543950335>';
153+
154+
export const isTypeSecp256k1Point = (type: string) => type === Literal.Secp256k1Point;
155+
156+
export const isCairo1Type = (type: string) => type.includes('::');
157+
/**
158+
* Retrieves the array type from the given type string.
159+
*
160+
* Works also for core::zeroable::NonZero type.
161+
* @param {string} type - The type string.
162+
* @returns - The array type.
163+
*/
164+
export const getArrayType = (type: string) => {
165+
return isCairo1Type(type)
166+
? type.substring(type.indexOf('<') + 1, type.lastIndexOf('>'))
167+
: type.replace('*', '');
168+
};
169+
170+
/**
171+
* Test if an ABI comes from a Cairo 1 contract
172+
* @param abi representing the interface of a Cairo contract
173+
* @returns TRUE if it is an ABI from a Cairo1 contract
174+
* @example
175+
* ```typescript
176+
* const isCairo1: boolean = isCairo1Abi(myAbi: Abi);
177+
* ```
178+
*/
179+
export function isCairo1Abi(abi: Abi): boolean {
180+
const { cairo } = getAbiContractVersion(abi);
181+
if (cairo === undefined) {
182+
throw Error('Unable to determine Cairo version');
183+
}
184+
return cairo === '1';
185+
}
186+
187+
/**
188+
* Checks if the given type is a NonZero type.
189+
*
190+
* @param {string} type The type to check.
191+
* @returns `true` if the type is NonZero type, `false` otherwise.
192+
* @example
193+
* ```typescript
194+
* const result = cairo.isTypeNonZero("core::zeroable::NonZero::<u8>");
195+
* //result = true
196+
* ```
197+
*/
198+
export function isTypeNonZero(type: string): boolean {
199+
return type.startsWith(NON_ZERO_PREFIX);
200+
}
201+
202+
/**
203+
* Return ContractVersion (Abi version) based on Abi
204+
* or undefined for unknown version
205+
* @param abi
206+
* @returns string
207+
*/
208+
export function getAbiContractVersion(abi: Abi): ContractVersion {
209+
// determine by interface for "Cairo 1.2"
210+
if (abi.find((it) => it.type === 'interface')) {
211+
return { cairo: '1', compiler: '2' };
212+
}
213+
214+
// determine by function io types "Cairo 1.1" or "Cairo 0.0"
215+
// find first function with inputs or outputs
216+
const testSubject = abi.find(
217+
(it) =>
218+
(it.type === 'function' || it.type === 'constructor') &&
219+
(it.inputs.length || it.outputs.length)
220+
);
221+
222+
if (!testSubject) {
223+
return { cairo: undefined, compiler: undefined };
224+
}
225+
const io = testSubject.inputs.length ? testSubject.inputs : testSubject.outputs;
226+
if (isCairo1Type(io[0].type)) {
227+
return { cairo: '1', compiler: '1' };
228+
}
229+
return { cairo: '0', compiler: '0' };
230+
}
231+
232+
/**
233+
* named tuple cairo type is described as js object {}
234+
* struct cairo type are described as js object {}
235+
* array cairo type are described as js array []
236+
*/
237+
238+
/**
239+
* Create Uint256 Cairo type (helper for common struct type)
240+
* @example
241+
* ```typescript
242+
* uint256('892349863487563453485768723498');
243+
* ```
244+
*/
245+
export const uint256 = (it: BigNumberish): Uint256 => {
246+
return new CairoUint256(it).toUint256DecimalString();
247+
};
248+
249+
/**
250+
* Create Uint512 Cairo type (helper for common struct type)
251+
* @param it BigNumberish representation of a 512 bits unsigned number
252+
* @returns Uint512 struct
253+
* @example
254+
* ```typescript
255+
* uint512('345745685892349863487563453485768723498');
256+
* ```
257+
*/
258+
export const uint512 = (it: BigNumberish): Uint512 => {
259+
return new CairoUint512(it).toUint512DecimalString();
260+
};
261+
262+
/**
263+
* Create unnamed tuple Cairo type (helper same as common struct type)
264+
* @example
265+
* ```typescript
266+
* tuple(1, '0x101', 16);
267+
* ```
268+
*/
269+
export const tuple = (
270+
...args: (BigNumberish | object | boolean)[]
271+
): Record<number, BigNumberish | object | boolean> => ({ ...args });
272+
273+
/**
274+
* Create felt Cairo type (cairo type helper)
275+
* @returns format: felt-string
276+
*/
277+
export function felt(it: BigNumberish): string {
278+
return CairoFelt(it);
279+
}

0 commit comments

Comments
 (0)