starknet_macros/
lib.rs

1//! Procedural macros for the `starknet` crate. This crate provides macros that help make defining
2//! certain compile-time constants easier.
3
4#![deny(missing_docs)]
5
6use proc_macro::TokenStream;
7use starknet_core::{
8    types::Felt,
9    utils::{cairo_short_string_to_felt, get_selector_from_name},
10};
11use syn::{parse_macro_input, LitStr};
12
13/// Defines a compile-time constant for a entrypoint selector of a Starknet contract.
14#[proc_macro]
15pub fn selector(input: TokenStream) -> TokenStream {
16    let input = parse_macro_input!(input as LitStr);
17
18    let str_value = input.value();
19
20    let selector_value = get_selector_from_name(&str_value).expect("invalid selector name");
21    let selector_raw = selector_value.to_raw();
22
23    format!(
24        "{}::from_raw([{}, {}, {}, {}])",
25        field_element_path(),
26        selector_raw[0],
27        selector_raw[1],
28        selector_raw[2],
29        selector_raw[3],
30    )
31    .parse()
32    .unwrap()
33}
34
35/// Defines a compile-time constant for a Cairo short string encoding from a human-readable string.
36#[proc_macro]
37pub fn short_string(input: TokenStream) -> TokenStream {
38    let input = parse_macro_input!(input as LitStr);
39
40    let str_value = input.value();
41
42    let felt_value = cairo_short_string_to_felt(&str_value).expect("invalid Cairo short string");
43    let felt_raw = felt_value.to_raw();
44
45    format!(
46        "{}::from_raw([{}, {}, {}, {}])",
47        field_element_path(),
48        felt_raw[0],
49        felt_raw[1],
50        felt_raw[2],
51        felt_raw[3],
52    )
53    .parse()
54    .unwrap()
55}
56
57/// Defines a compile-time constant for a field element from its decimal or hexadecimal
58/// representation.
59#[proc_macro]
60pub fn felt(input: TokenStream) -> TokenStream {
61    let input = parse_macro_input!(input as LitStr);
62
63    let str_value = input.value();
64
65    let felt_value = if str_value.starts_with("0x") {
66        Felt::from_hex(&str_value).expect("invalid Felt value")
67    } else {
68        Felt::from_dec_str(&str_value).expect("invalid Felt value")
69    };
70
71    let felt_raw = felt_value.to_raw();
72
73    format!(
74        "{}::from_raw([{}, {}, {}, {}])",
75        field_element_path(),
76        felt_raw[0],
77        felt_raw[1],
78        felt_raw[2],
79        felt_raw[3],
80    )
81    .parse()
82    .unwrap()
83}
84
85/// Defines a compile-time constant for a field element from its decimal representation.
86#[proc_macro]
87pub fn felt_dec(input: TokenStream) -> TokenStream {
88    let input = parse_macro_input!(input as LitStr);
89
90    let str_value = input.value();
91
92    let felt_value = Felt::from_dec_str(&str_value).expect("invalid Felt value");
93    let felt_raw = felt_value.to_raw();
94
95    format!(
96        "{}::from_raw([{}, {}, {}, {}])",
97        field_element_path(),
98        felt_raw[0],
99        felt_raw[1],
100        felt_raw[2],
101        felt_raw[3],
102    )
103    .parse()
104    .unwrap()
105}
106
107/// Defines a compile-time constant for a field element from its hexadecimal representation.
108#[proc_macro]
109pub fn felt_hex(input: TokenStream) -> TokenStream {
110    let input = parse_macro_input!(input as LitStr);
111
112    let str_value = input.value();
113
114    let felt_value = Felt::from_hex(&str_value).expect("invalid Felt value");
115    let felt_raw = felt_value.to_raw();
116
117    format!(
118        "{}::from_raw([{}, {}, {}, {}])",
119        field_element_path(),
120        felt_raw[0],
121        felt_raw[1],
122        felt_raw[2],
123        felt_raw[3],
124    )
125    .parse()
126    .unwrap()
127}
128
129#[cfg(feature = "use_imported_type")]
130const fn field_element_path() -> &'static str {
131    "Felt"
132}
133
134#[cfg(not(feature = "use_imported_type"))]
135const fn field_element_path() -> &'static str {
136    "::starknet::core::types::Felt"
137}