1#![allow(clippy::new_ret_no_self)]
16
17use crate::{
18    serde_hex,
19    utils::{
20        deserialize_from_byte_str,
21        serialize_as_byte_str,
22        trim_extra_whitespace,
23    },
24};
25#[cfg(not(feature = "std"))]
26use alloc::{
27    collections::BTreeMap,
28    format,
29    string::String,
30    vec,
31    vec::Vec,
32};
33use core::{
34    fmt::Display,
35    marker::PhantomData,
36};
37use scale_info::{
38    IntoPortable,
39    Registry,
40    TypeInfo,
41    form::{
42        Form,
43        MetaForm,
44        PortableForm,
45    },
46    meta_type,
47};
48use schemars::JsonSchema;
49use serde::{
50    Deserialize,
51    Serialize,
52    de::DeserializeOwned,
53};
54#[cfg(feature = "std")]
55use std::{
56    collections::BTreeMap,
57    hash::Hash,
58};
59
60#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
62#[serde(bound(
63    serialize = "F::Type: Serialize, F::String: Serialize",
64    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
65))]
66pub struct ContractSpec<F: Form = MetaForm>
67where
68    TypeSpec<F>: Default,
69{
70    constructors: Vec<ConstructorSpec<F>>,
72    messages: Vec<MessageSpec<F>>,
74    events: Vec<EventSpec<F>>,
76    docs: Vec<F::String>,
78    lang_error: TypeSpec<F>,
80    environment: EnvironmentSpec<F>,
82}
83
84impl IntoPortable for ContractSpec {
85    type Output = ContractSpec<PortableForm>;
86
87    fn into_portable(self, registry: &mut Registry) -> Self::Output {
88        ContractSpec {
89            constructors: self
90                .constructors
91                .into_iter()
92                .map(|constructor| constructor.into_portable(registry))
93                .collect::<Vec<_>>(),
94            messages: self
95                .messages
96                .into_iter()
97                .map(|msg| msg.into_portable(registry))
98                .collect::<Vec<_>>(),
99            events: self
100                .events
101                .into_iter()
102                .map(|event| event.into_portable(registry))
103                .collect::<Vec<_>>(),
104            docs: registry.map_into_portable(self.docs),
105            lang_error: self.lang_error.into_portable(registry),
106            environment: self.environment.into_portable(registry),
107        }
108    }
109}
110
111impl<F> ContractSpec<F>
112where
113    F: Form,
114    TypeSpec<F>: Default,
115{
116    pub fn constructors(&self) -> &[ConstructorSpec<F>] {
118        &self.constructors
119    }
120
121    pub fn messages(&self) -> &[MessageSpec<F>] {
123        &self.messages
124    }
125
126    pub fn events(&self) -> &[EventSpec<F>] {
128        &self.events
129    }
130
131    pub fn docs(&self) -> &[F::String] {
133        &self.docs
134    }
135
136    pub fn lang_error(&self) -> &TypeSpec<F> {
138        &self.lang_error
139    }
140    pub fn environment(&self) -> &EnvironmentSpec<F> {
142        &self.environment
143    }
144}
145
146pub enum Valid {}
148pub enum Invalid {}
150
151#[must_use]
152pub struct ContractSpecBuilder<F, S = Invalid>
153where
154    F: Form,
155    TypeSpec<F>: Default,
156{
157    spec: ContractSpec<F>,
159    marker: PhantomData<fn() -> S>,
161}
162
163impl<F> ContractSpecBuilder<F, Invalid>
164where
165    F: Form,
166    TypeSpec<F>: Default,
167{
168    pub fn constructors<C>(self, constructors: C) -> ContractSpecBuilder<F, Valid>
170    where
171        C: IntoIterator<Item = ConstructorSpec<F>>,
172    {
173        debug_assert!(self.spec.constructors.is_empty());
174        ContractSpecBuilder {
175            spec: ContractSpec {
176                constructors: constructors.into_iter().collect::<Vec<_>>(),
177                ..self.spec
178            },
179            marker: Default::default(),
180        }
181    }
182}
183
184impl<F, S> ContractSpecBuilder<F, S>
185where
186    F: Form,
187    TypeSpec<F>: Default,
188{
189    pub fn messages<M>(self, messages: M) -> Self
191    where
192        M: IntoIterator<Item = MessageSpec<F>>,
193    {
194        debug_assert!(self.spec.messages.is_empty());
195        Self {
196            spec: ContractSpec {
197                messages: messages.into_iter().collect::<Vec<_>>(),
198                ..self.spec
199            },
200            ..self
201        }
202    }
203
204    pub fn events<E>(self, events: E) -> Self
206    where
207        E: IntoIterator<Item = EventSpec<F>>,
208    {
209        debug_assert!(self.spec.events.is_empty());
210        Self {
211            spec: ContractSpec {
212                events: events.into_iter().collect::<Vec<_>>(),
213                ..self.spec
214            },
215            ..self
216        }
217    }
218
219    pub fn docs<D>(self, docs: D) -> Self
221    where
222        D: IntoIterator<Item = <F as Form>::String>,
223    {
224        debug_assert!(self.spec.docs.is_empty());
225        Self {
226            spec: ContractSpec {
227                docs: docs.into_iter().collect::<Vec<_>>(),
228                ..self.spec
229            },
230            ..self
231        }
232    }
233
234    pub fn lang_error(self, lang_error: TypeSpec<F>) -> Self {
236        Self {
237            spec: ContractSpec {
238                lang_error,
239                ..self.spec
240            },
241            ..self
242        }
243    }
244
245    pub fn environment(self, environment: EnvironmentSpec<F>) -> Self {
247        Self {
248            spec: ContractSpec {
249                environment,
250                ..self.spec
251            },
252            ..self
253        }
254    }
255}
256
257impl<F> ContractSpecBuilder<F, Valid>
258where
259    F: Form,
260    F::String: Display,
261    TypeSpec<F>: Default,
262{
263    #[allow(clippy::arithmetic_side_effects)] pub fn done(self) -> ContractSpec<F> {
266        assert!(
267            !self.spec.constructors.is_empty(),
268            "must have at least one constructor"
269        );
270        assert!(
271            !self.spec.messages.is_empty(),
272            "must have at least one message"
273        );
274        assert!(
275            self.spec.constructors.iter().filter(|c| c.default).count() < 2,
276            "only one default constructor is allowed"
277        );
278        assert!(
279            self.spec.messages.iter().filter(|m| m.default).count() < 2,
280            "only one default message is allowed"
281        );
282
283        const MAX_TOPICS: usize = 4;
284        let events_exceeding_max_topics_limit = self
285            .spec
286            .events
287            .iter()
288            .filter_map(|e| {
289                let signature_topic = if e.signature_topic.is_some() { 1 } else { 0 };
290                let topics_count =
291                    signature_topic + e.args.iter().filter(|a| a.indexed).count();
292                if topics_count > MAX_TOPICS {
293                    Some(format!(
294                        "`{}::{}` ({} topics)",
295                        e.module_path, e.label, topics_count
296                    ))
297                } else {
298                    None
299                }
300            })
301            .collect::<Vec<_>>();
302        assert!(
303            events_exceeding_max_topics_limit.is_empty(),
304            "maximum of {MAX_TOPICS} event topics exceeded: {}",
305            events_exceeding_max_topics_limit.join(", ")
306        );
307
308        let mut signature_topics: BTreeMap<Vec<u8>, Vec<String>> = BTreeMap::new();
309        for e in self.spec.events.iter() {
310            if let Some(signature_topic) = &e.signature_topic {
311                signature_topics
312                    .entry(signature_topic.bytes.clone())
313                    .or_default()
314                    .push(format!("`{}::{}`", e.module_path, e.label));
315            }
316        }
317        let signature_topic_collisions = signature_topics
318            .iter()
319            .filter_map(|(_, topics)| {
320                if topics.len() > 1 {
321                    Some(format!(
322                        "event signature topic collision: {}",
323                        topics.join(", ")
324                    ))
325                } else {
326                    None
327                }
328            })
329            .collect::<Vec<_>>();
330        assert!(
331            signature_topic_collisions.is_empty(),
332            "{}",
333            signature_topic_collisions.join("\n")
334        );
335
336        self.spec
337    }
338}
339
340impl<F> ContractSpec<F>
341where
342    F: Form,
343    TypeSpec<F>: Default,
344    EnvironmentSpec<F>: Default,
345{
346    pub fn new() -> ContractSpecBuilder<F, Invalid> {
348        ContractSpecBuilder {
349            spec: Self {
350                constructors: Vec::new(),
351                messages: Vec::new(),
352                events: Vec::new(),
353                docs: Vec::new(),
354                lang_error: Default::default(),
355                environment: Default::default(),
356            },
357            marker: PhantomData,
358        }
359    }
360}
361
362#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
364#[serde(bound(
365    serialize = "F::Type: Serialize, F::String: Serialize",
366    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned",
367))]
368#[serde(rename_all = "camelCase")]
369pub struct ConstructorSpec<F: Form = MetaForm> {
370    pub label: F::String,
375    pub selector: Selector,
377    pub payable: bool,
379    pub args: Vec<MessageParamSpec<F>>,
381    pub return_type: ReturnTypeSpec<F>,
383    pub docs: Vec<F::String>,
385    default: bool,
387}
388
389impl IntoPortable for ConstructorSpec {
390    type Output = ConstructorSpec<PortableForm>;
391
392    fn into_portable(self, registry: &mut Registry) -> Self::Output {
393        ConstructorSpec {
394            label: self.label.to_string(),
395            selector: self.selector,
396            payable: self.payable,
397            args: self
398                .args
399                .into_iter()
400                .map(|arg| arg.into_portable(registry))
401                .collect::<Vec<_>>(),
402            return_type: self.return_type.into_portable(registry),
403            docs: self.docs.into_iter().map(|s| s.into()).collect(),
404            default: self.default,
405        }
406    }
407}
408
409impl<F> ConstructorSpec<F>
410where
411    F: Form,
412{
413    pub fn label(&self) -> &F::String {
418        &self.label
419    }
420
421    pub fn selector(&self) -> &Selector {
423        &self.selector
424    }
425
426    pub fn payable(&self) -> bool {
428        self.payable
429    }
430
431    pub fn args(&self) -> &[MessageParamSpec<F>] {
433        &self.args
434    }
435
436    pub fn return_type(&self) -> &ReturnTypeSpec<F> {
438        &self.return_type
439    }
440
441    pub fn docs(&self) -> &[F::String] {
443        &self.docs
444    }
445
446    pub fn default(&self) -> bool {
447        self.default
448    }
449}
450
451#[allow(clippy::type_complexity)]
459#[must_use]
460pub struct ConstructorSpecBuilder<F: Form, Selector, IsPayable, Returns> {
461    spec: ConstructorSpec<F>,
462    marker: PhantomData<fn() -> (Selector, IsPayable, Returns)>,
463}
464
465impl<F> ConstructorSpec<F>
466where
467    F: Form,
468    TypeSpec<F>: Default,
469{
470    pub fn from_label(
472        label: <F as Form>::String,
473    ) -> ConstructorSpecBuilder<
474        F,
475        Missing<state::Selector>,
476        Missing<state::IsPayable>,
477        Missing<state::Returns>,
478    > {
479        ConstructorSpecBuilder {
480            spec: Self {
481                label,
482                selector: Selector::default(),
483                payable: Default::default(),
484                args: Vec::new(),
485                return_type: ReturnTypeSpec::new(TypeSpec::default()),
486                docs: Vec::new(),
487                default: false,
488            },
489            marker: PhantomData,
490        }
491    }
492}
493
494impl<F, P, R> ConstructorSpecBuilder<F, Missing<state::Selector>, P, R>
495where
496    F: Form,
497{
498    pub fn selector(
500        self,
501        selector: [u8; 4],
502    ) -> ConstructorSpecBuilder<F, state::Selector, P, R> {
503        ConstructorSpecBuilder {
504            spec: ConstructorSpec {
505                selector: selector.into(),
506                ..self.spec
507            },
508            marker: PhantomData,
509        }
510    }
511}
512
513impl<F, S, R> ConstructorSpecBuilder<F, S, Missing<state::IsPayable>, R>
514where
515    F: Form,
516{
517    pub fn payable(
519        self,
520        is_payable: bool,
521    ) -> ConstructorSpecBuilder<F, S, state::IsPayable, R> {
522        ConstructorSpecBuilder {
523            spec: ConstructorSpec {
524                payable: is_payable,
525                ..self.spec
526            },
527            marker: PhantomData,
528        }
529    }
530}
531
532impl<F, S, P> ConstructorSpecBuilder<F, S, P, Missing<state::Returns>>
533where
534    F: Form,
535{
536    pub fn returns(
538        self,
539        return_type: ReturnTypeSpec<F>,
540    ) -> ConstructorSpecBuilder<F, S, P, state::Returns> {
541        ConstructorSpecBuilder {
542            spec: ConstructorSpec {
543                return_type,
544                ..self.spec
545            },
546            marker: PhantomData,
547        }
548    }
549}
550
551impl<F, S, P, R> ConstructorSpecBuilder<F, S, P, R>
552where
553    F: Form,
554{
555    pub fn args<A>(self, args: A) -> Self
557    where
558        A: IntoIterator<Item = MessageParamSpec<F>>,
559    {
560        let mut this = self;
561        debug_assert!(this.spec.args.is_empty());
562        this.spec.args = args.into_iter().collect::<Vec<_>>();
563        this
564    }
565
566    pub fn docs<'a, D>(self, docs: D) -> Self
568    where
569        D: IntoIterator<Item = &'a str>,
570        F::String: From<&'a str>,
571    {
572        let mut this = self;
573        debug_assert!(this.spec.docs.is_empty());
574        this.spec.docs = docs
575            .into_iter()
576            .map(|s| trim_extra_whitespace(s).into())
577            .collect::<Vec<_>>();
578        this
579    }
580
581    pub fn default(self, default: bool) -> Self {
583        ConstructorSpecBuilder {
584            spec: ConstructorSpec {
585                default,
586                ..self.spec
587            },
588            marker: PhantomData,
589        }
590    }
591}
592
593impl<F> ConstructorSpecBuilder<F, state::Selector, state::IsPayable, state::Returns>
594where
595    F: Form,
596{
597    pub fn done(self) -> ConstructorSpec<F> {
599        self.spec
600    }
601}
602
603#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
605#[serde(bound(
606    serialize = "F::Type: Serialize, F::String: Serialize",
607    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
608))]
609#[serde(rename_all = "camelCase")]
610pub struct MessageSpec<F: Form = MetaForm> {
611    label: F::String,
616    selector: Selector,
618    mutates: bool,
620    payable: bool,
622    args: Vec<MessageParamSpec<F>>,
624    return_type: ReturnTypeSpec<F>,
626    docs: Vec<F::String>,
628    default: bool,
630}
631
632pub struct Missing<S>(PhantomData<fn() -> S>);
635
636mod state {
637    pub struct Selector;
642    pub struct Mutates;
644    pub struct IsPayable;
646    pub struct Returns;
648    pub struct AccountId;
650    pub struct Balance;
652    pub struct Hash;
654    pub struct Timestamp;
656    pub struct BlockNumber;
658    pub struct NativeToEthRatio;
660    pub struct BufferSize;
662}
663
664impl<F> MessageSpec<F>
665where
666    F: Form,
667    TypeSpec<F>: Default,
668{
669    pub fn from_label(
671        label: <F as Form>::String,
672    ) -> MessageSpecBuilder<
673        F,
674        Missing<state::Selector>,
675        Missing<state::Mutates>,
676        Missing<state::IsPayable>,
677        Missing<state::Returns>,
678    > {
679        MessageSpecBuilder {
680            spec: Self {
681                label,
682                selector: Selector::default(),
683                mutates: false,
684                payable: false,
685                args: Vec::new(),
686                return_type: ReturnTypeSpec::new(TypeSpec::default()),
687                docs: Vec::new(),
688                default: false,
689            },
690            marker: PhantomData,
691        }
692    }
693}
694
695impl<F> MessageSpec<F>
696where
697    F: Form,
698{
699    pub fn label(&self) -> &F::String {
704        &self.label
705    }
706
707    pub fn selector(&self) -> &Selector {
709        &self.selector
710    }
711
712    pub fn mutates(&self) -> bool {
714        self.mutates
715    }
716
717    pub fn payable(&self) -> bool {
719        self.payable
720    }
721
722    pub fn args(&self) -> &[MessageParamSpec<F>] {
724        &self.args
725    }
726
727    pub fn return_type(&self) -> &ReturnTypeSpec<F> {
729        &self.return_type
730    }
731
732    pub fn docs(&self) -> &[F::String] {
734        &self.docs
735    }
736
737    pub fn default(&self) -> bool {
738        self.default
739    }
740}
741
742#[allow(clippy::type_complexity)]
750#[must_use]
751pub struct MessageSpecBuilder<F, Selector, Mutates, IsPayable, Returns>
752where
753    F: Form,
754{
755    spec: MessageSpec<F>,
756    marker: PhantomData<fn() -> (Selector, Mutates, IsPayable, Returns)>,
757}
758
759impl<F, M, P, R> MessageSpecBuilder<F, Missing<state::Selector>, M, P, R>
760where
761    F: Form,
762{
763    pub fn selector(
765        self,
766        selector: [u8; 4],
767    ) -> MessageSpecBuilder<F, state::Selector, M, P, R> {
768        MessageSpecBuilder {
769            spec: MessageSpec {
770                selector: selector.into(),
771                ..self.spec
772            },
773            marker: PhantomData,
774        }
775    }
776}
777
778impl<F, S, P, R> MessageSpecBuilder<F, S, Missing<state::Mutates>, P, R>
779where
780    F: Form,
781{
782    pub fn mutates(
785        self,
786        mutates: bool,
787    ) -> MessageSpecBuilder<F, S, state::Mutates, P, R> {
788        MessageSpecBuilder {
789            spec: MessageSpec {
790                mutates,
791                ..self.spec
792            },
793            marker: PhantomData,
794        }
795    }
796}
797
798impl<F, S, M, R> MessageSpecBuilder<F, S, M, Missing<state::IsPayable>, R>
799where
800    F: Form,
801{
802    pub fn payable(
804        self,
805        is_payable: bool,
806    ) -> MessageSpecBuilder<F, S, M, state::IsPayable, R> {
807        MessageSpecBuilder {
808            spec: MessageSpec {
809                payable: is_payable,
810                ..self.spec
811            },
812            marker: PhantomData,
813        }
814    }
815}
816
817impl<F, M, S, P> MessageSpecBuilder<F, S, M, P, Missing<state::Returns>>
818where
819    F: Form,
820{
821    pub fn returns(
823        self,
824        return_type: ReturnTypeSpec<F>,
825    ) -> MessageSpecBuilder<F, S, M, P, state::Returns> {
826        MessageSpecBuilder {
827            spec: MessageSpec {
828                return_type,
829                ..self.spec
830            },
831            marker: PhantomData,
832        }
833    }
834}
835
836impl<F, S, M, P, R> MessageSpecBuilder<F, S, M, P, R>
837where
838    F: Form,
839{
840    pub fn args<A>(self, args: A) -> Self
842    where
843        A: IntoIterator<Item = MessageParamSpec<F>>,
844    {
845        let mut this = self;
846        debug_assert!(this.spec.args.is_empty());
847        this.spec.args = args.into_iter().collect::<Vec<_>>();
848        this
849    }
850
851    pub fn docs<D>(self, docs: D) -> Self
853    where
854        D: IntoIterator<Item = <F as Form>::String>,
855    {
856        let mut this = self;
857        debug_assert!(this.spec.docs.is_empty());
858        this.spec.docs = docs.into_iter().collect::<Vec<_>>();
859        this
860    }
861
862    pub fn default(self, default: bool) -> Self {
864        MessageSpecBuilder {
865            spec: MessageSpec {
866                default,
867                ..self.spec
868            },
869            marker: PhantomData,
870        }
871    }
872}
873
874impl<F>
875    MessageSpecBuilder<
876        F,
877        state::Selector,
878        state::Mutates,
879        state::IsPayable,
880        state::Returns,
881    >
882where
883    F: Form,
884{
885    pub fn done(self) -> MessageSpec<F> {
887        self.spec
888    }
889}
890
891impl IntoPortable for MessageSpec {
892    type Output = MessageSpec<PortableForm>;
893
894    fn into_portable(self, registry: &mut Registry) -> Self::Output {
895        MessageSpec {
896            label: self.label.to_string(),
897            selector: self.selector,
898            mutates: self.mutates,
899            payable: self.payable,
900            default: self.default,
901            args: self
902                .args
903                .into_iter()
904                .map(|arg| arg.into_portable(registry))
905                .collect::<Vec<_>>(),
906            return_type: self.return_type.into_portable(registry),
907            docs: self.docs.into_iter().map(|s| s.into()).collect(),
908        }
909    }
910}
911
912#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
914#[serde(bound(
915    serialize = "F::Type: Serialize, F::String: Serialize",
916    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
917))]
918pub struct EventSpec<F: Form = MetaForm> {
919    label: F::String,
921    module_path: F::String,
923    signature_topic: Option<SignatureTopic>,
925    args: Vec<EventParamSpec<F>>,
927    docs: Vec<F::String>,
929}
930
931#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
933#[serde(transparent)]
934pub struct SignatureTopic {
935    #[serde(
936        serialize_with = "serialize_as_byte_str",
937        deserialize_with = "deserialize_from_byte_str"
938    )]
939    bytes: Vec<u8>,
940}
941
942impl<T> From<T> for SignatureTopic
943where
944    T: AsRef<[u8]>,
945{
946    fn from(bytes: T) -> Self {
947        SignatureTopic {
948            bytes: bytes.as_ref().to_vec(),
949        }
950    }
951}
952
953impl SignatureTopic {
954    pub fn as_bytes(&self) -> &[u8] {
956        &self.bytes
957    }
958}
959
960#[must_use]
962pub struct EventSpecBuilder<F>
963where
964    F: Form,
965{
966    spec: EventSpec<F>,
967}
968
969impl<F> EventSpecBuilder<F>
970where
971    F: Form,
972{
973    pub fn module_path<'a>(self, path: &'a str) -> Self
975    where
976        F::String: From<&'a str>,
977    {
978        let mut this = self;
979        this.spec.module_path = path.into();
980        this
981    }
982
983    pub fn args<A>(self, args: A) -> Self
985    where
986        A: IntoIterator<Item = EventParamSpec<F>>,
987    {
988        let mut this = self;
989        debug_assert!(this.spec.args.is_empty());
990        this.spec.args = args.into_iter().collect::<Vec<_>>();
991        this
992    }
993
994    pub fn signature_topic<T>(self, topic: Option<T>) -> Self
996    where
997        T: AsRef<[u8]>,
998    {
999        let mut this = self;
1000        debug_assert!(this.spec.signature_topic.is_none());
1001        this.spec.signature_topic = topic.as_ref().map(SignatureTopic::from);
1002        this
1003    }
1004
1005    pub fn docs<'a, D>(self, docs: D) -> Self
1007    where
1008        D: IntoIterator<Item = &'a str>,
1009        F::String: From<&'a str>,
1010    {
1011        let mut this = self;
1012        debug_assert!(this.spec.docs.is_empty());
1013        this.spec.docs = docs
1014            .into_iter()
1015            .map(|s| trim_extra_whitespace(s).into())
1016            .collect::<Vec<_>>();
1017        this
1018    }
1019
1020    pub fn done(self) -> EventSpec<F> {
1022        self.spec
1023    }
1024}
1025
1026impl IntoPortable for EventSpec {
1027    type Output = EventSpec<PortableForm>;
1028
1029    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1030        EventSpec {
1031            label: self.label.to_string(),
1032            module_path: self.module_path.to_string(),
1033            signature_topic: self.signature_topic,
1034            args: self
1035                .args
1036                .into_iter()
1037                .map(|arg| arg.into_portable(registry))
1038                .collect::<Vec<_>>(),
1039            docs: self.docs.into_iter().map(|s| s.into()).collect(),
1040        }
1041    }
1042}
1043
1044impl<F> EventSpec<F>
1045where
1046    F: Form,
1047    F::String: Default,
1048{
1049    pub fn new(label: <F as Form>::String) -> EventSpecBuilder<F> {
1051        EventSpecBuilder {
1052            spec: Self {
1053                label,
1054                module_path: Default::default(),
1055                signature_topic: None,
1056                args: Vec::new(),
1057                docs: Vec::new(),
1058            },
1059        }
1060    }
1061}
1062
1063impl<F> EventSpec<F>
1064where
1065    F: Form,
1066{
1067    pub fn label(&self) -> &F::String {
1069        &self.label
1070    }
1071
1072    pub fn args(&self) -> &[EventParamSpec<F>] {
1074        &self.args
1075    }
1076
1077    pub fn signature_topic(&self) -> Option<&SignatureTopic> {
1079        self.signature_topic.as_ref()
1080    }
1081
1082    pub fn docs(&self) -> &[F::String] {
1084        &self.docs
1085    }
1086}
1087
1088#[cfg_attr(feature = "std", derive(Hash))]
1090#[derive(Debug, Default, PartialEq, Eq, derive_more::From, JsonSchema)]
1091pub struct Selector(#[schemars(with = "String")] [u8; 4]);
1092
1093impl serde::Serialize for Selector {
1094    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1095    where
1096        S: serde::Serializer,
1097    {
1098        serde_hex::serialize(&self.0, serializer)
1099    }
1100}
1101
1102impl<'de> serde::Deserialize<'de> for Selector {
1103    fn deserialize<D>(d: D) -> Result<Self, D::Error>
1104    where
1105        D: serde::Deserializer<'de>,
1106    {
1107        let mut arr = [0; 4];
1108        serde_hex::deserialize_check_len(d, serde_hex::ExpectedLen::Exact(&mut arr[..]))?;
1109        Ok(arr.into())
1110    }
1111}
1112
1113impl Selector {
1114    pub fn new<T>(bytes: T) -> Self
1116    where
1117        T: Into<[u8; 4]>,
1118    {
1119        Self(bytes.into())
1120    }
1121
1122    pub fn to_bytes(&self) -> &[u8] {
1124        &self.0
1125    }
1126}
1127
1128pub type DisplayName<F> = scale_info::Path<F>;
1146
1147#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1165#[serde(bound(
1166    serialize = "F::Type: Serialize, F::String: Serialize",
1167    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1168))]
1169#[serde(rename_all = "camelCase")]
1170pub struct TypeSpec<F: Form = MetaForm> {
1171    #[serde(rename = "type")]
1173    ty: F::Type,
1174    display_name: DisplayName<F>,
1176}
1177
1178impl Default for TypeSpec<MetaForm> {
1179    fn default() -> Self {
1180        TypeSpec::of_type::<()>()
1181    }
1182}
1183
1184impl Default for TypeSpec<PortableForm> {
1185    fn default() -> Self {
1186        Self {
1187            ty: u32::default().into(),
1188            display_name: Default::default(),
1189        }
1190    }
1191}
1192
1193impl IntoPortable for TypeSpec {
1194    type Output = TypeSpec<PortableForm>;
1195
1196    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1197        TypeSpec {
1198            ty: registry.register_type(&self.ty),
1199            display_name: self.display_name.into_portable(registry),
1200        }
1201    }
1202}
1203
1204impl TypeSpec {
1205    pub fn with_name_str<T>(display_name: &'static str) -> Self
1217    where
1218        T: TypeInfo + 'static,
1219    {
1220        Self::with_name_segs::<T, _>(display_name.split("::"))
1221    }
1222
1223    pub fn with_name_segs<T, S>(segments: S) -> Self
1236    where
1237        T: TypeInfo + 'static,
1238        S: IntoIterator<Item = &'static str>,
1239    {
1240        Self {
1241            ty: meta_type::<T>(),
1242            display_name: DisplayName::from_segments(segments)
1243                .unwrap_or_else(|err| panic!("display name is invalid: {err:?}")),
1244        }
1245    }
1246
1247    pub fn of_type<T>() -> Self
1255    where
1256        T: TypeInfo + 'static,
1257    {
1258        Self {
1259            ty: meta_type::<T>(),
1260            display_name: DisplayName::default(),
1261        }
1262    }
1263}
1264
1265impl<F> TypeSpec<F>
1266where
1267    F: Form,
1268{
1269    pub fn ty(&self) -> &F::Type {
1271        &self.ty
1272    }
1273
1274    pub fn display_name(&self) -> &DisplayName<F> {
1276        &self.display_name
1277    }
1278
1279    pub fn new(ty: <F as Form>::Type, display_name: DisplayName<F>) -> Self {
1281        Self { ty, display_name }
1282    }
1283}
1284
1285#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1287#[serde(bound(
1288    serialize = "F::Type: Serialize, F::String: Serialize",
1289    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1290))]
1291pub struct EventParamSpec<F: Form = MetaForm> {
1292    label: F::String,
1294    indexed: bool,
1296    #[serde(rename = "type")]
1298    ty: TypeSpec<F>,
1299    docs: Vec<F::String>,
1301}
1302
1303impl IntoPortable for EventParamSpec {
1304    type Output = EventParamSpec<PortableForm>;
1305
1306    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1307        EventParamSpec {
1308            label: self.label.to_string(),
1309            indexed: self.indexed,
1310            ty: self.ty.into_portable(registry),
1311            docs: self.docs.into_iter().map(|s| s.into()).collect(),
1312        }
1313    }
1314}
1315
1316impl<F> EventParamSpec<F>
1317where
1318    F: Form,
1319    TypeSpec<F>: Default,
1320{
1321    pub fn new(label: F::String) -> EventParamSpecBuilder<F> {
1323        EventParamSpecBuilder {
1324            spec: Self {
1325                label,
1326                indexed: false,
1328                ty: Default::default(),
1330                docs: vec![],
1332            },
1333        }
1334    }
1335    pub fn label(&self) -> &F::String {
1337        &self.label
1338    }
1339
1340    pub fn indexed(&self) -> bool {
1342        self.indexed
1343    }
1344
1345    pub fn ty(&self) -> &TypeSpec<F> {
1347        &self.ty
1348    }
1349
1350    pub fn docs(&self) -> &[F::String] {
1352        &self.docs
1353    }
1354}
1355
1356#[must_use]
1358pub struct EventParamSpecBuilder<F>
1359where
1360    F: Form,
1361{
1362    spec: EventParamSpec<F>,
1364}
1365
1366impl<F> EventParamSpecBuilder<F>
1367where
1368    F: Form,
1369{
1370    pub fn of_type(self, spec: TypeSpec<F>) -> Self {
1372        let mut this = self;
1373        this.spec.ty = spec;
1374        this
1375    }
1376
1377    pub fn indexed(self, is_indexed: bool) -> Self {
1379        let mut this = self;
1380        this.spec.indexed = is_indexed;
1381        this
1382    }
1383
1384    pub fn docs<'a, D>(self, docs: D) -> Self
1386    where
1387        D: IntoIterator<Item = &'a str>,
1388        F::String: From<&'a str>,
1389    {
1390        debug_assert!(self.spec.docs.is_empty());
1391        Self {
1392            spec: EventParamSpec {
1393                docs: docs
1394                    .into_iter()
1395                    .map(|s| trim_extra_whitespace(s).into())
1396                    .collect::<Vec<_>>(),
1397                ..self.spec
1398            },
1399        }
1400    }
1401
1402    pub fn done(self) -> EventParamSpec<F> {
1404        self.spec
1405    }
1406}
1407
1408#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1410#[serde(transparent)]
1411#[serde(bound(
1412    serialize = "F::Type: Serialize, F::String: Serialize",
1413    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1414))]
1415#[must_use]
1416pub struct ReturnTypeSpec<F: Form = MetaForm> {
1417    #[serde(rename = "type")]
1418    ret_type: TypeSpec<F>,
1419}
1420
1421impl IntoPortable for ReturnTypeSpec {
1422    type Output = ReturnTypeSpec<PortableForm>;
1423
1424    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1425        ReturnTypeSpec {
1426            ret_type: self.ret_type.into_portable(registry),
1427        }
1428    }
1429}
1430
1431impl<F> ReturnTypeSpec<F>
1432where
1433    F: Form,
1434    TypeSpec<F>: Default,
1435{
1436    pub fn new<T>(ty: T) -> Self
1445    where
1446        T: Into<TypeSpec<F>>,
1447    {
1448        Self {
1449            ret_type: ty.into(),
1450        }
1451    }
1452
1453    pub fn ret_type(&self) -> &TypeSpec<F> {
1455        &self.ret_type
1456    }
1457}
1458
1459#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1461#[serde(bound(
1462    serialize = "F::Type: Serialize, F::String: Serialize",
1463    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1464))]
1465pub struct MessageParamSpec<F: Form = MetaForm> {
1466    label: F::String,
1468    #[serde(rename = "type")]
1470    ty: TypeSpec<F>,
1471}
1472
1473impl IntoPortable for MessageParamSpec {
1474    type Output = MessageParamSpec<PortableForm>;
1475
1476    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1477        MessageParamSpec {
1478            label: self.label.to_string(),
1479            ty: self.ty.into_portable(registry),
1480        }
1481    }
1482}
1483
1484impl<F> MessageParamSpec<F>
1485where
1486    F: Form,
1487    TypeSpec<F>: Default,
1488{
1489    pub fn new(label: F::String) -> MessageParamSpecBuilder<F> {
1491        MessageParamSpecBuilder {
1492            spec: Self {
1493                label,
1494                ty: TypeSpec::default(),
1496            },
1497        }
1498    }
1499
1500    pub fn label(&self) -> &F::String {
1502        &self.label
1503    }
1504
1505    pub fn ty(&self) -> &TypeSpec<F> {
1507        &self.ty
1508    }
1509}
1510
1511#[must_use]
1513pub struct MessageParamSpecBuilder<F: Form> {
1514    spec: MessageParamSpec<F>,
1516}
1517
1518impl<F> MessageParamSpecBuilder<F>
1519where
1520    F: Form,
1521{
1522    pub fn of_type(self, ty: TypeSpec<F>) -> Self {
1524        let mut this = self;
1525        this.spec.ty = ty;
1526        this
1527    }
1528
1529    pub fn done(self) -> MessageParamSpec<F> {
1531        self.spec
1532    }
1533}
1534
1535#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1537#[serde(bound(
1538    serialize = "F::Type: Serialize, F::String: Serialize",
1539    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1540))]
1541#[serde(rename_all = "camelCase")]
1542pub struct EnvironmentSpec<F: Form = MetaForm>
1543where
1544    TypeSpec<F>: Default,
1545{
1546    account_id: TypeSpec<F>,
1547    balance: TypeSpec<F>,
1548    hash: TypeSpec<F>,
1549    timestamp: TypeSpec<F>,
1550    block_number: TypeSpec<F>,
1551    native_to_eth_ratio: u32,
1552    static_buffer_size: usize,
1553}
1554
1555impl<F> Default for EnvironmentSpec<F>
1556where
1557    F: Form,
1558    TypeSpec<F>: Default,
1559{
1560    fn default() -> Self {
1561        Self {
1562            account_id: Default::default(),
1563            balance: Default::default(),
1564            hash: Default::default(),
1565            timestamp: Default::default(),
1566            block_number: Default::default(),
1567            native_to_eth_ratio: Default::default(),
1568            static_buffer_size: Default::default(),
1569        }
1570    }
1571}
1572
1573impl IntoPortable for EnvironmentSpec {
1574    type Output = EnvironmentSpec<PortableForm>;
1575
1576    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1577        EnvironmentSpec {
1578            account_id: self.account_id.into_portable(registry),
1579            balance: self.balance.into_portable(registry),
1580            hash: self.hash.into_portable(registry),
1581            timestamp: self.timestamp.into_portable(registry),
1582            block_number: self.block_number.into_portable(registry),
1583            native_to_eth_ratio: self.native_to_eth_ratio,
1584            static_buffer_size: self.static_buffer_size,
1585        }
1586    }
1587}
1588
1589impl<F> EnvironmentSpec<F>
1590where
1591    F: Form,
1592    TypeSpec<F>: Default,
1593{
1594    pub fn account_id(&self) -> &TypeSpec<F> {
1596        &self.account_id
1597    }
1598    pub fn balance(&self) -> &TypeSpec<F> {
1600        &self.balance
1601    }
1602    pub fn hash(&self) -> &TypeSpec<F> {
1604        &self.hash
1605    }
1606    pub fn timestamp(&self) -> &TypeSpec<F> {
1608        &self.timestamp
1609    }
1610    pub fn block_number(&self) -> &TypeSpec<F> {
1612        &self.block_number
1613    }
1614    pub fn native_to_eth_ratio(&self) -> u32 {
1616        self.native_to_eth_ratio
1617    }
1618}
1619
1620#[allow(clippy::type_complexity)]
1621impl<F> EnvironmentSpec<F>
1622where
1623    F: Form,
1624    TypeSpec<F>: Default,
1625    EnvironmentSpec<F>: Default,
1626{
1627    pub fn new() -> EnvironmentSpecBuilder<
1628        F,
1629        Missing<state::AccountId>,
1630        Missing<state::Balance>,
1631        Missing<state::Hash>,
1632        Missing<state::Timestamp>,
1633        Missing<state::BlockNumber>,
1634        Missing<state::NativeToEthRatio>,
1635        Missing<state::BufferSize>,
1636    > {
1637        EnvironmentSpecBuilder {
1638            spec: Default::default(),
1639            marker: PhantomData,
1640        }
1641    }
1642}
1643
1644#[allow(clippy::type_complexity)]
1646#[must_use]
1647pub struct EnvironmentSpecBuilder<F, A, B, H, T, BN, NTER, BS>
1648where
1649    F: Form,
1650    TypeSpec<F>: Default,
1651    EnvironmentSpec<F>: Default,
1652{
1653    spec: EnvironmentSpec<F>,
1654    marker: PhantomData<fn() -> (A, B, H, T, BN, NTER, BS)>,
1655}
1656
1657impl<F, B, H, T, BN, NTER, BS>
1658    EnvironmentSpecBuilder<F, Missing<state::AccountId>, B, H, T, BN, NTER, BS>
1659where
1660    F: Form,
1661    TypeSpec<F>: Default,
1662    EnvironmentSpec<F>: Default,
1663{
1664    pub fn account_id(
1666        self,
1667        account_id: TypeSpec<F>,
1668    ) -> EnvironmentSpecBuilder<F, state::AccountId, B, H, T, BN, NTER, BS> {
1669        EnvironmentSpecBuilder {
1670            spec: EnvironmentSpec {
1671                account_id,
1672                ..self.spec
1673            },
1674            marker: PhantomData,
1675        }
1676    }
1677}
1678
1679impl<F, A, H, T, BN, NTER, BS>
1680    EnvironmentSpecBuilder<F, A, Missing<state::Balance>, H, T, BN, NTER, BS>
1681where
1682    F: Form,
1683    TypeSpec<F>: Default,
1684    EnvironmentSpec<F>: Default,
1685{
1686    pub fn balance(
1688        self,
1689        balance: TypeSpec<F>,
1690    ) -> EnvironmentSpecBuilder<F, A, state::Balance, H, T, BN, NTER, BS> {
1691        EnvironmentSpecBuilder {
1692            spec: EnvironmentSpec {
1693                balance,
1694                ..self.spec
1695            },
1696            marker: PhantomData,
1697        }
1698    }
1699}
1700
1701impl<F, A, B, T, BN, NTER, BS>
1702    EnvironmentSpecBuilder<F, A, B, Missing<state::Hash>, T, BN, NTER, BS>
1703where
1704    F: Form,
1705    TypeSpec<F>: Default,
1706    EnvironmentSpec<F>: Default,
1707{
1708    pub fn hash(
1710        self,
1711        hash: TypeSpec<F>,
1712    ) -> EnvironmentSpecBuilder<F, A, B, state::Hash, T, BN, NTER, BS> {
1713        EnvironmentSpecBuilder {
1714            spec: EnvironmentSpec { hash, ..self.spec },
1715            marker: PhantomData,
1716        }
1717    }
1718}
1719
1720impl<F, A, B, H, BN, NTER, BS>
1721    EnvironmentSpecBuilder<F, A, B, H, Missing<state::Timestamp>, BN, NTER, BS>
1722where
1723    F: Form,
1724    TypeSpec<F>: Default,
1725    EnvironmentSpec<F>: Default,
1726{
1727    pub fn timestamp(
1729        self,
1730        timestamp: TypeSpec<F>,
1731    ) -> EnvironmentSpecBuilder<F, A, B, H, state::Timestamp, BN, NTER, BS> {
1732        EnvironmentSpecBuilder {
1733            spec: EnvironmentSpec {
1734                timestamp,
1735                ..self.spec
1736            },
1737            marker: PhantomData,
1738        }
1739    }
1740}
1741
1742impl<F, A, B, H, T, NTER, BS>
1743    EnvironmentSpecBuilder<F, A, B, H, T, Missing<state::BlockNumber>, NTER, BS>
1744where
1745    F: Form,
1746    TypeSpec<F>: Default,
1747    EnvironmentSpec<F>: Default,
1748{
1749    pub fn block_number(
1751        self,
1752        block_number: TypeSpec<F>,
1753    ) -> EnvironmentSpecBuilder<F, A, B, H, T, state::BlockNumber, NTER, BS> {
1754        EnvironmentSpecBuilder {
1755            spec: EnvironmentSpec {
1756                block_number,
1757                ..self.spec
1758            },
1759            marker: PhantomData,
1760        }
1761    }
1762}
1763
1764impl<F, A, B, H, T, BN, BS>
1765    EnvironmentSpecBuilder<F, A, B, H, T, BN, Missing<state::NativeToEthRatio>, BS>
1766where
1767    F: Form,
1768    TypeSpec<F>: Default,
1769    EnvironmentSpec<F>: Default,
1770{
1771    pub fn native_to_eth_ratio(
1773        self,
1774        native_to_eth_ratio: u32,
1775    ) -> EnvironmentSpecBuilder<F, A, B, H, T, BN, state::NativeToEthRatio, BS> {
1776        EnvironmentSpecBuilder {
1777            spec: EnvironmentSpec {
1778                native_to_eth_ratio,
1779                ..self.spec
1780            },
1781            marker: PhantomData,
1782        }
1783    }
1784}
1785
1786impl<F, A, B, H, T, BN, NTER>
1787    EnvironmentSpecBuilder<F, A, B, H, T, BN, NTER, Missing<state::BufferSize>>
1788where
1789    F: Form,
1790    TypeSpec<F>: Default,
1791    EnvironmentSpec<F>: Default,
1792{
1793    pub fn static_buffer_size(
1795        self,
1796        static_buffer_size: usize,
1797    ) -> EnvironmentSpecBuilder<F, A, B, H, T, BN, NTER, state::BufferSize> {
1798        EnvironmentSpecBuilder {
1799            spec: EnvironmentSpec {
1800                static_buffer_size,
1801                ..self.spec
1802            },
1803            marker: PhantomData,
1804        }
1805    }
1806}
1807
1808impl<F>
1809    EnvironmentSpecBuilder<
1810        F,
1811        state::AccountId,
1812        state::Balance,
1813        state::Hash,
1814        state::Timestamp,
1815        state::BlockNumber,
1816        state::NativeToEthRatio,
1817        state::BufferSize,
1818    >
1819where
1820    F: Form,
1821    TypeSpec<F>: Default,
1822    EnvironmentSpec<F>: Default,
1823{
1824    pub fn done(self) -> EnvironmentSpec<F> {
1826        self.spec
1827    }
1828}