ink_metadata/
specs.rs

1// Copyright (C) Use Ink (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![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/// Describes a contract.
61#[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    /// The set of constructors of the contract.
71    constructors: Vec<ConstructorSpec<F>>,
72    /// The external messages of the contract.
73    messages: Vec<MessageSpec<F>>,
74    /// The events of the contract.
75    events: Vec<EventSpec<F>>,
76    /// The contract documentation.
77    docs: Vec<F::String>,
78    /// The language specific error type.
79    lang_error: TypeSpec<F>,
80    /// The environment types of the contract specification.
81    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    /// Returns the set of constructors of the contract.
117    pub fn constructors(&self) -> &[ConstructorSpec<F>] {
118        &self.constructors
119    }
120
121    /// Returns the external messages of the contract.
122    pub fn messages(&self) -> &[MessageSpec<F>] {
123        &self.messages
124    }
125
126    /// Returns the events of the contract.
127    pub fn events(&self) -> &[EventSpec<F>] {
128        &self.events
129    }
130
131    /// Returns the contract documentation.
132    pub fn docs(&self) -> &[F::String] {
133        &self.docs
134    }
135
136    /// Returns the language error type.
137    pub fn lang_error(&self) -> &TypeSpec<F> {
138        &self.lang_error
139    }
140    // Returns the environment types of the contract specification.
141    pub fn environment(&self) -> &EnvironmentSpec<F> {
142        &self.environment
143    }
144}
145
146/// The message builder is ready to finalize construction.
147pub enum Valid {}
148/// The message builder is not ready to finalize construction.
149pub enum Invalid {}
150
151#[must_use]
152pub struct ContractSpecBuilder<F, S = Invalid>
153where
154    F: Form,
155    TypeSpec<F>: Default,
156{
157    /// The to-be-constructed contract specification.
158    spec: ContractSpec<F>,
159    /// Marker for compile-time checking of valid contract specifications.
160    marker: PhantomData<fn() -> S>,
161}
162
163impl<F> ContractSpecBuilder<F, Invalid>
164where
165    F: Form,
166    TypeSpec<F>: Default,
167{
168    /// Sets the constructors of the contract specification.
169    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    /// Sets the messages of the contract specification.
190    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    /// Sets the events of the contract specification.
205    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    /// Sets the documentation of the contract specification.
220    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    /// Sets the language error of the contract specification.
235    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    /// Sets the environment types of the contract specification.
246    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    /// Finalizes construction of the contract specification.
264    #[allow(clippy::arithmetic_side_effects)] // todo
265    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    /// Creates a new contract specification.
347    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/// Describes a constructor of a contract.
363#[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    /// The label of the constructor.
371    ///
372    /// In case of a trait provided constructor the label is prefixed with the trait
373    /// label.
374    pub label: F::String,
375    /// The selector hash of the message.
376    pub selector: Selector,
377    /// If the constructor accepts any `value` from the caller.
378    pub payable: bool,
379    /// The parameters of the deployment handler.
380    pub args: Vec<MessageParamSpec<F>>,
381    /// The return type of the constructor..
382    pub return_type: ReturnTypeSpec<F>,
383    /// The deployment handler documentation.
384    pub docs: Vec<F::String>,
385    /// If the constructor is the default for off-chain consumers (e.g UIs).
386    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    /// Returns the label of the constructor.
414    ///
415    /// In case of a trait provided constructor the label is prefixed with the trait
416    /// label.
417    pub fn label(&self) -> &F::String {
418        &self.label
419    }
420
421    /// Returns the selector hash of the constructor.
422    pub fn selector(&self) -> &Selector {
423        &self.selector
424    }
425
426    /// Returns if the constructor is payable by the caller.
427    pub fn payable(&self) -> bool {
428        self.payable
429    }
430
431    /// Returns the parameters of the deployment handler.
432    pub fn args(&self) -> &[MessageParamSpec<F>] {
433        &self.args
434    }
435
436    /// Returns the return type of the constructor.
437    pub fn return_type(&self) -> &ReturnTypeSpec<F> {
438        &self.return_type
439    }
440
441    /// Returns the deployment handler documentation.
442    pub fn docs(&self) -> &[F::String] {
443        &self.docs
444    }
445
446    pub fn default(&self) -> bool {
447        self.default
448    }
449}
450
451/// A builder for constructors.
452///
453/// # Developer Note
454///
455/// Some fields are guarded by a type-state pattern to fail at
456/// compile-time instead of at run-time. This is useful to better
457/// debug code-gen macros.
458#[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    /// Creates a new constructor spec builder.
471    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    /// Sets the function selector of the message.
499    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    /// Sets if the constructor is payable, thus accepting value for the caller.
518    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    /// Sets the return type of the constructor.
537    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    /// Sets the input arguments of the constructor specification.
556    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    /// Sets the documentation of the constructor specification.
567    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    /// Sets the default of the constructor specification.
582    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    /// Finishes construction of the constructor.
598    pub fn done(self) -> ConstructorSpec<F> {
599        self.spec
600    }
601}
602
603/// Describes a contract message.
604#[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    /// The label of the message.
612    ///
613    /// In case of trait provided messages and constructors the prefix
614    /// by convention in ink! is the label of the trait.
615    label: F::String,
616    /// The selector hash of the message.
617    selector: Selector,
618    /// If the message is allowed to mutate the contract state.
619    mutates: bool,
620    /// If the message accepts any `value` from the caller.
621    payable: bool,
622    /// The parameters of the message.
623    args: Vec<MessageParamSpec<F>>,
624    /// The return type of the message.
625    return_type: ReturnTypeSpec<F>,
626    /// The message documentation.
627    docs: Vec<F::String>,
628    /// If the message is the default for off-chain consumers (e.g UIs).
629    default: bool,
630}
631
632/// Type state for builders to tell that some mandatory state has not yet been set
633/// yet or to fail upon setting the same state multiple times.
634pub struct Missing<S>(PhantomData<fn() -> S>);
635
636mod state {
637    //! Type states that tell what state of a message has not
638    //! yet been set properly for a valid construction.
639
640    /// Type state for the message selector of a message.
641    pub struct Selector;
642    /// Type state for the mutability of a message.
643    pub struct Mutates;
644    /// Type state for telling if the message is payable.
645    pub struct IsPayable;
646    /// Type state for the message return type.
647    pub struct Returns;
648    /// Type state for the `AccountId` type of the environment.
649    pub struct AccountId;
650    /// Type state for the `Balance` type of the environment.
651    pub struct Balance;
652    /// Type state for the `Hash` type of the environment.
653    pub struct Hash;
654    /// Type state for the `Timestamp` type of the environment.
655    pub struct Timestamp;
656    /// Type state for the `BlockNumber` type of the environment.
657    pub struct BlockNumber;
658    /// Type state for the native to eth ratio specified in the environment.
659    pub struct NativeToEthRatio;
660    /// Type state for the trust backed assets precompile index specified in the
661    /// environment.
662    pub struct TrustBackedAssetsPrecompileIndex;
663    /// Type state for the pool assets precompile index specified in the environment.
664    pub struct PoolAssetsPrecompileIndex;
665    /// Type state for the size of the static buffer configured via environment variable.`
666    pub struct BufferSize;
667}
668
669impl<F> MessageSpec<F>
670where
671    F: Form,
672    TypeSpec<F>: Default,
673{
674    /// Creates a new message spec builder.
675    pub fn from_label(
676        label: <F as Form>::String,
677    ) -> MessageSpecBuilder<
678        F,
679        Missing<state::Selector>,
680        Missing<state::Mutates>,
681        Missing<state::IsPayable>,
682        Missing<state::Returns>,
683    > {
684        MessageSpecBuilder {
685            spec: Self {
686                label,
687                selector: Selector::default(),
688                mutates: false,
689                payable: false,
690                args: Vec::new(),
691                return_type: ReturnTypeSpec::new(TypeSpec::default()),
692                docs: Vec::new(),
693                default: false,
694            },
695            marker: PhantomData,
696        }
697    }
698}
699
700impl<F> MessageSpec<F>
701where
702    F: Form,
703{
704    /// Returns the label of the message.
705    ///
706    /// In case of trait provided messages and constructors the prefix
707    /// by convention in ink! is the label of the trait.
708    pub fn label(&self) -> &F::String {
709        &self.label
710    }
711
712    /// Returns the selector hash of the message.
713    pub fn selector(&self) -> &Selector {
714        &self.selector
715    }
716
717    /// Returns true if the message is allowed to mutate the contract state.
718    pub fn mutates(&self) -> bool {
719        self.mutates
720    }
721
722    /// Returns true if the message is payable by the caller.
723    pub fn payable(&self) -> bool {
724        self.payable
725    }
726
727    /// Returns the parameters of the message.
728    pub fn args(&self) -> &[MessageParamSpec<F>] {
729        &self.args
730    }
731
732    /// Returns the return type of the message.
733    pub fn return_type(&self) -> &ReturnTypeSpec<F> {
734        &self.return_type
735    }
736
737    /// Returns the message documentation.
738    pub fn docs(&self) -> &[F::String] {
739        &self.docs
740    }
741
742    pub fn default(&self) -> bool {
743        self.default
744    }
745}
746
747/// A builder for messages.
748///
749/// # Developer Note
750///
751/// Some fields are guarded by a type-state pattern to fail at
752/// compile-time instead of at run-time. This is useful to better
753/// debug code-gen macros.
754#[allow(clippy::type_complexity)]
755#[must_use]
756pub struct MessageSpecBuilder<F, Selector, Mutates, IsPayable, Returns>
757where
758    F: Form,
759{
760    spec: MessageSpec<F>,
761    marker: PhantomData<fn() -> (Selector, Mutates, IsPayable, Returns)>,
762}
763
764impl<F, M, P, R> MessageSpecBuilder<F, Missing<state::Selector>, M, P, R>
765where
766    F: Form,
767{
768    /// Sets the function selector of the message.
769    pub fn selector(
770        self,
771        selector: [u8; 4],
772    ) -> MessageSpecBuilder<F, state::Selector, M, P, R> {
773        MessageSpecBuilder {
774            spec: MessageSpec {
775                selector: selector.into(),
776                ..self.spec
777            },
778            marker: PhantomData,
779        }
780    }
781}
782
783impl<F, S, P, R> MessageSpecBuilder<F, S, Missing<state::Mutates>, P, R>
784where
785    F: Form,
786{
787    /// Sets if the message is mutable, thus taking `&mut self` or not thus taking
788    /// `&self`.
789    pub fn mutates(
790        self,
791        mutates: bool,
792    ) -> MessageSpecBuilder<F, S, state::Mutates, P, R> {
793        MessageSpecBuilder {
794            spec: MessageSpec {
795                mutates,
796                ..self.spec
797            },
798            marker: PhantomData,
799        }
800    }
801}
802
803impl<F, S, M, R> MessageSpecBuilder<F, S, M, Missing<state::IsPayable>, R>
804where
805    F: Form,
806{
807    /// Sets if the message is payable, thus accepting value for the caller.
808    pub fn payable(
809        self,
810        is_payable: bool,
811    ) -> MessageSpecBuilder<F, S, M, state::IsPayable, R> {
812        MessageSpecBuilder {
813            spec: MessageSpec {
814                payable: is_payable,
815                ..self.spec
816            },
817            marker: PhantomData,
818        }
819    }
820}
821
822impl<F, M, S, P> MessageSpecBuilder<F, S, M, P, Missing<state::Returns>>
823where
824    F: Form,
825{
826    /// Sets the return type of the message.
827    pub fn returns(
828        self,
829        return_type: ReturnTypeSpec<F>,
830    ) -> MessageSpecBuilder<F, S, M, P, state::Returns> {
831        MessageSpecBuilder {
832            spec: MessageSpec {
833                return_type,
834                ..self.spec
835            },
836            marker: PhantomData,
837        }
838    }
839}
840
841impl<F, S, M, P, R> MessageSpecBuilder<F, S, M, P, R>
842where
843    F: Form,
844{
845    /// Sets the input arguments of the message specification.
846    pub fn args<A>(self, args: A) -> Self
847    where
848        A: IntoIterator<Item = MessageParamSpec<F>>,
849    {
850        let mut this = self;
851        debug_assert!(this.spec.args.is_empty());
852        this.spec.args = args.into_iter().collect::<Vec<_>>();
853        this
854    }
855
856    /// Sets the documentation of the message specification.
857    pub fn docs<D>(self, docs: D) -> Self
858    where
859        D: IntoIterator<Item = <F as Form>::String>,
860    {
861        let mut this = self;
862        debug_assert!(this.spec.docs.is_empty());
863        this.spec.docs = docs.into_iter().collect::<Vec<_>>();
864        this
865    }
866
867    /// Sets the default of the message specification.
868    pub fn default(self, default: bool) -> Self {
869        MessageSpecBuilder {
870            spec: MessageSpec {
871                default,
872                ..self.spec
873            },
874            marker: PhantomData,
875        }
876    }
877}
878
879impl<F>
880    MessageSpecBuilder<
881        F,
882        state::Selector,
883        state::Mutates,
884        state::IsPayable,
885        state::Returns,
886    >
887where
888    F: Form,
889{
890    /// Finishes construction of the message.
891    pub fn done(self) -> MessageSpec<F> {
892        self.spec
893    }
894}
895
896impl IntoPortable for MessageSpec {
897    type Output = MessageSpec<PortableForm>;
898
899    fn into_portable(self, registry: &mut Registry) -> Self::Output {
900        MessageSpec {
901            label: self.label.to_string(),
902            selector: self.selector,
903            mutates: self.mutates,
904            payable: self.payable,
905            default: self.default,
906            args: self
907                .args
908                .into_iter()
909                .map(|arg| arg.into_portable(registry))
910                .collect::<Vec<_>>(),
911            return_type: self.return_type.into_portable(registry),
912            docs: self.docs.into_iter().map(|s| s.into()).collect(),
913        }
914    }
915}
916
917/// Describes an event definition.
918#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
919#[serde(bound(
920    serialize = "F::Type: Serialize, F::String: Serialize",
921    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
922))]
923pub struct EventSpec<F: Form = MetaForm> {
924    /// The label of the event.
925    label: F::String,
926    /// The module path to the event type definition.
927    module_path: F::String,
928    /// The signature topic of the event. `None` if the event is anonymous.
929    signature_topic: Option<SignatureTopic>,
930    /// The event arguments.
931    args: Vec<EventParamSpec<F>>,
932    /// The event documentation.
933    docs: Vec<F::String>,
934}
935
936/// The value of the signature topic for a non anonymous event.
937#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
938#[serde(transparent)]
939pub struct SignatureTopic {
940    #[serde(
941        serialize_with = "serialize_as_byte_str",
942        deserialize_with = "deserialize_from_byte_str"
943    )]
944    bytes: Vec<u8>,
945}
946
947impl<T> From<T> for SignatureTopic
948where
949    T: AsRef<[u8]>,
950{
951    fn from(bytes: T) -> Self {
952        SignatureTopic {
953            bytes: bytes.as_ref().to_vec(),
954        }
955    }
956}
957
958impl SignatureTopic {
959    /// Returns the bytes of the signature topic.
960    pub fn as_bytes(&self) -> &[u8] {
961        &self.bytes
962    }
963}
964
965/// An event specification builder.
966#[must_use]
967pub struct EventSpecBuilder<F>
968where
969    F: Form,
970{
971    spec: EventSpec<F>,
972}
973
974impl<F> EventSpecBuilder<F>
975where
976    F: Form,
977{
978    /// Sets the module path to the event type definition.
979    pub fn module_path<'a>(self, path: &'a str) -> Self
980    where
981        F::String: From<&'a str>,
982    {
983        let mut this = self;
984        this.spec.module_path = path.into();
985        this
986    }
987
988    /// Sets the input arguments of the event specification.
989    pub fn args<A>(self, args: A) -> Self
990    where
991        A: IntoIterator<Item = EventParamSpec<F>>,
992    {
993        let mut this = self;
994        debug_assert!(this.spec.args.is_empty());
995        this.spec.args = args.into_iter().collect::<Vec<_>>();
996        this
997    }
998
999    /// Sets the signature topic of the event specification.
1000    pub fn signature_topic<T>(self, topic: Option<T>) -> Self
1001    where
1002        T: AsRef<[u8]>,
1003    {
1004        let mut this = self;
1005        debug_assert!(this.spec.signature_topic.is_none());
1006        this.spec.signature_topic = topic.as_ref().map(SignatureTopic::from);
1007        this
1008    }
1009
1010    /// Sets the input arguments of the event specification.
1011    pub fn docs<'a, D>(self, docs: D) -> Self
1012    where
1013        D: IntoIterator<Item = &'a str>,
1014        F::String: From<&'a str>,
1015    {
1016        let mut this = self;
1017        debug_assert!(this.spec.docs.is_empty());
1018        this.spec.docs = docs
1019            .into_iter()
1020            .map(|s| trim_extra_whitespace(s).into())
1021            .collect::<Vec<_>>();
1022        this
1023    }
1024
1025    /// Finalizes building the event specification.
1026    pub fn done(self) -> EventSpec<F> {
1027        self.spec
1028    }
1029}
1030
1031impl IntoPortable for EventSpec {
1032    type Output = EventSpec<PortableForm>;
1033
1034    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1035        EventSpec {
1036            label: self.label.to_string(),
1037            module_path: self.module_path.to_string(),
1038            signature_topic: self.signature_topic,
1039            args: self
1040                .args
1041                .into_iter()
1042                .map(|arg| arg.into_portable(registry))
1043                .collect::<Vec<_>>(),
1044            docs: self.docs.into_iter().map(|s| s.into()).collect(),
1045        }
1046    }
1047}
1048
1049impl<F> EventSpec<F>
1050where
1051    F: Form,
1052    F::String: Default,
1053{
1054    /// Creates a new event specification builder.
1055    pub fn new(label: <F as Form>::String) -> EventSpecBuilder<F> {
1056        EventSpecBuilder {
1057            spec: Self {
1058                label,
1059                module_path: Default::default(),
1060                signature_topic: None,
1061                args: Vec::new(),
1062                docs: Vec::new(),
1063            },
1064        }
1065    }
1066}
1067
1068impl<F> EventSpec<F>
1069where
1070    F: Form,
1071{
1072    /// Returns the label of the event.
1073    pub fn label(&self) -> &F::String {
1074        &self.label
1075    }
1076
1077    /// The event arguments.
1078    pub fn args(&self) -> &[EventParamSpec<F>] {
1079        &self.args
1080    }
1081
1082    /// The signature topic of the event. `None` if the event is anonymous.
1083    pub fn signature_topic(&self) -> Option<&SignatureTopic> {
1084        self.signature_topic.as_ref()
1085    }
1086
1087    /// The event documentation.
1088    pub fn docs(&self) -> &[F::String] {
1089        &self.docs
1090    }
1091}
1092
1093/// The 4 byte selector to identify constructors and messages
1094#[cfg_attr(feature = "std", derive(Hash))]
1095#[derive(Debug, Default, PartialEq, Eq, derive_more::From, JsonSchema)]
1096pub struct Selector(#[schemars(with = "String")] [u8; 4]);
1097
1098impl serde::Serialize for Selector {
1099    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1100    where
1101        S: serde::Serializer,
1102    {
1103        serde_hex::serialize(&self.0, serializer)
1104    }
1105}
1106
1107impl<'de> serde::Deserialize<'de> for Selector {
1108    fn deserialize<D>(d: D) -> Result<Self, D::Error>
1109    where
1110        D: serde::Deserializer<'de>,
1111    {
1112        let mut arr = [0; 4];
1113        serde_hex::deserialize_check_len(d, serde_hex::ExpectedLen::Exact(&mut arr[..]))?;
1114        Ok(arr.into())
1115    }
1116}
1117
1118impl Selector {
1119    /// Create a new custom selector.
1120    pub fn new<T>(bytes: T) -> Self
1121    where
1122        T: Into<[u8; 4]>,
1123    {
1124        Self(bytes.into())
1125    }
1126
1127    /// Returns the underlying selector bytes.
1128    pub fn to_bytes(&self) -> &[u8] {
1129        &self.0
1130    }
1131}
1132
1133/// Describes the syntactical name of a type at a given type position.
1134///
1135/// This is important when trying to work with type aliases.
1136/// Normally a type alias is transparent and so scenarios such as
1137/// ```no_compile
1138/// type Foo = i32;
1139/// fn bar(foo: Foo);
1140/// ```
1141/// Will only communicate that `foo` is of type `i32` which is correct,
1142/// however, it will miss the potentially important information that it
1143/// is being used through a type alias named `Foo`.
1144///
1145/// In ink! we currently experience this problem with environmental types
1146/// such as the `Balance` type that is just a type alias to `u128` in the
1147/// default setup. Even though it would be useful for third party tools
1148/// such as the Polkadot UI to know that we are handling with `Balance`
1149/// types, we currently cannot communicate this without display names.
1150pub type DisplayName<F> = scale_info::Path<F>;
1151
1152/// A type specification.
1153///
1154/// This contains the actual type as well as an optional compile-time
1155/// known displayed representation of the type. This is useful for cases
1156/// where the type is used through a type alias in order to provide
1157/// information about the alias name.
1158///
1159/// # Examples
1160///
1161/// Consider the following Rust function:
1162/// ```no_compile
1163/// fn is_sorted(input: &[i32], pred: Predicate) -> bool;
1164/// ```
1165/// In this above example `input` would have no displayable name,
1166/// `pred`s display name is `Predicate` and the display name of
1167/// the return type is simply `bool`. Note that `Predicate` could
1168/// simply be a type alias to `fn(i32, i32) -> Ordering`.
1169#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1170#[serde(bound(
1171    serialize = "F::Type: Serialize, F::String: Serialize",
1172    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1173))]
1174#[serde(rename_all = "camelCase")]
1175pub struct TypeSpec<F: Form = MetaForm> {
1176    /// The actual type.
1177    #[serde(rename = "type")]
1178    ty: F::Type,
1179    /// The compile-time known displayed representation of the type.
1180    display_name: DisplayName<F>,
1181}
1182
1183impl Default for TypeSpec<MetaForm> {
1184    fn default() -> Self {
1185        TypeSpec::of_type::<()>()
1186    }
1187}
1188
1189impl Default for TypeSpec<PortableForm> {
1190    fn default() -> Self {
1191        Self {
1192            ty: u32::default().into(),
1193            display_name: Default::default(),
1194        }
1195    }
1196}
1197
1198impl IntoPortable for TypeSpec {
1199    type Output = TypeSpec<PortableForm>;
1200
1201    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1202        TypeSpec {
1203            ty: registry.register_type(&self.ty),
1204            display_name: self.display_name.into_portable(registry),
1205        }
1206    }
1207}
1208
1209impl TypeSpec {
1210    /// Creates a new type specification with a display name.
1211    ///
1212    /// The name is any valid Rust identifier or path.
1213    ///
1214    /// # Examples
1215    ///
1216    /// Valid display names are `foo`, `foo::bar`, `foo::bar::Baz`, etc.
1217    ///
1218    /// # Panics
1219    ///
1220    /// Panics if the given display name is invalid.
1221    pub fn with_name_str<T>(display_name: &'static str) -> Self
1222    where
1223        T: TypeInfo + 'static,
1224    {
1225        Self::with_name_segs::<T, _>(display_name.split("::"))
1226    }
1227
1228    /// Creates a new type specification with a display name
1229    /// represented by the given path segments.
1230    ///
1231    /// The display name segments all must be valid Rust identifiers.
1232    ///
1233    /// # Examples
1234    ///
1235    /// Valid display names are `foo`, `foo::bar`, `foo::bar::Baz`, etc.
1236    ///
1237    /// # Panics
1238    ///
1239    /// Panics if the given display name is invalid.
1240    pub fn with_name_segs<T, S>(segments: S) -> Self
1241    where
1242        T: TypeInfo + 'static,
1243        S: IntoIterator<Item = &'static str>,
1244    {
1245        Self {
1246            ty: meta_type::<T>(),
1247            display_name: DisplayName::from_segments(segments)
1248                .unwrap_or_else(|err| panic!("display name is invalid: {err:?}")),
1249        }
1250    }
1251
1252    /// Creates a new type specification without a display name.
1253    ///
1254    /// Example:
1255    /// ```no_run
1256    /// # use ink_metadata::{TypeSpec, ReturnTypeSpec};
1257    /// ReturnTypeSpec::new(TypeSpec::of_type::<i32>()); // return type of `i32`
1258    /// ```
1259    pub fn of_type<T>() -> Self
1260    where
1261        T: TypeInfo + 'static,
1262    {
1263        Self {
1264            ty: meta_type::<T>(),
1265            display_name: DisplayName::default(),
1266        }
1267    }
1268}
1269
1270impl<F> TypeSpec<F>
1271where
1272    F: Form,
1273{
1274    /// Returns the actual type.
1275    pub fn ty(&self) -> &F::Type {
1276        &self.ty
1277    }
1278
1279    /// Returns the compile-time known displayed representation of the type.
1280    pub fn display_name(&self) -> &DisplayName<F> {
1281        &self.display_name
1282    }
1283
1284    /// Creates a new type specification for a given type and display name.
1285    pub fn new(ty: <F as Form>::Type, display_name: DisplayName<F>) -> Self {
1286        Self { ty, display_name }
1287    }
1288}
1289
1290/// Describes a pair of parameter label and type.
1291#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1292#[serde(bound(
1293    serialize = "F::Type: Serialize, F::String: Serialize",
1294    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1295))]
1296pub struct EventParamSpec<F: Form = MetaForm> {
1297    /// The label of the parameter.
1298    label: F::String,
1299    /// If the event parameter is indexed as a topic.
1300    indexed: bool,
1301    /// The type of the parameter.
1302    #[serde(rename = "type")]
1303    ty: TypeSpec<F>,
1304    /// The documentation associated with the arguments.
1305    docs: Vec<F::String>,
1306}
1307
1308impl IntoPortable for EventParamSpec {
1309    type Output = EventParamSpec<PortableForm>;
1310
1311    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1312        EventParamSpec {
1313            label: self.label.to_string(),
1314            indexed: self.indexed,
1315            ty: self.ty.into_portable(registry),
1316            docs: self.docs.into_iter().map(|s| s.into()).collect(),
1317        }
1318    }
1319}
1320
1321impl<F> EventParamSpec<F>
1322where
1323    F: Form,
1324    TypeSpec<F>: Default,
1325{
1326    /// Creates a new event parameter specification builder.
1327    pub fn new(label: F::String) -> EventParamSpecBuilder<F> {
1328        EventParamSpecBuilder {
1329            spec: Self {
1330                label,
1331                // By default event parameters are not indexed as topics.
1332                indexed: false,
1333                // We initialize every parameter type as `()`.
1334                ty: Default::default(),
1335                // We start with empty docs.
1336                docs: vec![],
1337            },
1338        }
1339    }
1340    /// Returns the label of the parameter.
1341    pub fn label(&self) -> &F::String {
1342        &self.label
1343    }
1344
1345    /// Returns true if the event parameter is indexed as a topic.
1346    pub fn indexed(&self) -> bool {
1347        self.indexed
1348    }
1349
1350    /// Returns the type of the parameter.
1351    pub fn ty(&self) -> &TypeSpec<F> {
1352        &self.ty
1353    }
1354
1355    /// Returns the documentation associated with the arguments.
1356    pub fn docs(&self) -> &[F::String] {
1357        &self.docs
1358    }
1359}
1360
1361/// Used to construct an event parameter specification.
1362#[must_use]
1363pub struct EventParamSpecBuilder<F>
1364where
1365    F: Form,
1366{
1367    /// The built-up event parameter specification.
1368    spec: EventParamSpec<F>,
1369}
1370
1371impl<F> EventParamSpecBuilder<F>
1372where
1373    F: Form,
1374{
1375    /// Sets the type of the event parameter.
1376    pub fn of_type(self, spec: TypeSpec<F>) -> Self {
1377        let mut this = self;
1378        this.spec.ty = spec;
1379        this
1380    }
1381
1382    /// If the event parameter is indexed as a topic.
1383    pub fn indexed(self, is_indexed: bool) -> Self {
1384        let mut this = self;
1385        this.spec.indexed = is_indexed;
1386        this
1387    }
1388
1389    /// Sets the documentation of the event parameter.
1390    pub fn docs<'a, D>(self, docs: D) -> Self
1391    where
1392        D: IntoIterator<Item = &'a str>,
1393        F::String: From<&'a str>,
1394    {
1395        debug_assert!(self.spec.docs.is_empty());
1396        Self {
1397            spec: EventParamSpec {
1398                docs: docs
1399                    .into_iter()
1400                    .map(|s| trim_extra_whitespace(s).into())
1401                    .collect::<Vec<_>>(),
1402                ..self.spec
1403            },
1404        }
1405    }
1406
1407    /// Finishes constructing the event parameter spec.
1408    pub fn done(self) -> EventParamSpec<F> {
1409        self.spec
1410    }
1411}
1412
1413/// Describes the contract message return type.
1414#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1415#[serde(transparent)]
1416#[serde(bound(
1417    serialize = "F::Type: Serialize, F::String: Serialize",
1418    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1419))]
1420#[must_use]
1421pub struct ReturnTypeSpec<F: Form = MetaForm> {
1422    #[serde(rename = "type")]
1423    ret_type: TypeSpec<F>,
1424}
1425
1426impl IntoPortable for ReturnTypeSpec {
1427    type Output = ReturnTypeSpec<PortableForm>;
1428
1429    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1430        ReturnTypeSpec {
1431            ret_type: self.ret_type.into_portable(registry),
1432        }
1433    }
1434}
1435
1436impl<F> ReturnTypeSpec<F>
1437where
1438    F: Form,
1439    TypeSpec<F>: Default,
1440{
1441    /// Creates a new return type specification from the given type or `None`.
1442    ///
1443    /// # Examples
1444    ///
1445    /// ```no_run
1446    /// # use ink_metadata::{TypeSpec, ReturnTypeSpec};
1447    /// <ReturnTypeSpec<scale_info::form::MetaForm>>::new(TypeSpec::default()); // no return type;
1448    /// ```
1449    pub fn new<T>(ty: T) -> Self
1450    where
1451        T: Into<TypeSpec<F>>,
1452    {
1453        Self {
1454            ret_type: ty.into(),
1455        }
1456    }
1457
1458    /// Returns the return type
1459    pub fn ret_type(&self) -> &TypeSpec<F> {
1460        &self.ret_type
1461    }
1462}
1463
1464/// Describes a pair of parameter label and type.
1465#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1466#[serde(bound(
1467    serialize = "F::Type: Serialize, F::String: Serialize",
1468    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1469))]
1470pub struct MessageParamSpec<F: Form = MetaForm> {
1471    /// The label of the parameter.
1472    label: F::String,
1473    /// The type of the parameter.
1474    #[serde(rename = "type")]
1475    ty: TypeSpec<F>,
1476}
1477
1478impl IntoPortable for MessageParamSpec {
1479    type Output = MessageParamSpec<PortableForm>;
1480
1481    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1482        MessageParamSpec {
1483            label: self.label.to_string(),
1484            ty: self.ty.into_portable(registry),
1485        }
1486    }
1487}
1488
1489impl<F> MessageParamSpec<F>
1490where
1491    F: Form,
1492    TypeSpec<F>: Default,
1493{
1494    /// Constructs a new message parameter specification via builder.
1495    pub fn new(label: F::String) -> MessageParamSpecBuilder<F> {
1496        MessageParamSpecBuilder {
1497            spec: Self {
1498                label,
1499                // Uses `()` type by default.
1500                ty: TypeSpec::default(),
1501            },
1502        }
1503    }
1504
1505    /// Returns the label of the parameter.
1506    pub fn label(&self) -> &F::String {
1507        &self.label
1508    }
1509
1510    /// Returns the type of the parameter.
1511    pub fn ty(&self) -> &TypeSpec<F> {
1512        &self.ty
1513    }
1514}
1515
1516/// Used to construct a message parameter specification.
1517#[must_use]
1518pub struct MessageParamSpecBuilder<F: Form> {
1519    /// The to-be-constructed message parameter specification.
1520    spec: MessageParamSpec<F>,
1521}
1522
1523impl<F> MessageParamSpecBuilder<F>
1524where
1525    F: Form,
1526{
1527    /// Sets the type of the message parameter.
1528    pub fn of_type(self, ty: TypeSpec<F>) -> Self {
1529        let mut this = self;
1530        this.spec.ty = ty;
1531        this
1532    }
1533
1534    /// Finishes construction of the message parameter.
1535    pub fn done(self) -> MessageParamSpec<F> {
1536        self.spec
1537    }
1538}
1539
1540/// Describes a contract environment.
1541#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1542#[serde(bound(
1543    serialize = "F::Type: Serialize, F::String: Serialize",
1544    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1545))]
1546#[serde(rename_all = "camelCase")]
1547pub struct EnvironmentSpec<F: Form = MetaForm>
1548where
1549    TypeSpec<F>: Default,
1550{
1551    account_id: TypeSpec<F>,
1552    balance: TypeSpec<F>,
1553    hash: TypeSpec<F>,
1554    timestamp: TypeSpec<F>,
1555    block_number: TypeSpec<F>,
1556    native_to_eth_ratio: u32,
1557    trust_backed_assets_precompile_index: u16,
1558    pool_assets_precompile_index: u16,
1559    static_buffer_size: usize,
1560}
1561
1562impl<F> Default for EnvironmentSpec<F>
1563where
1564    F: Form,
1565    TypeSpec<F>: Default,
1566{
1567    fn default() -> Self {
1568        Self {
1569            account_id: Default::default(),
1570            balance: Default::default(),
1571            hash: Default::default(),
1572            timestamp: Default::default(),
1573            block_number: Default::default(),
1574            native_to_eth_ratio: Default::default(),
1575            trust_backed_assets_precompile_index: Default::default(),
1576            pool_assets_precompile_index: Default::default(),
1577            static_buffer_size: Default::default(),
1578        }
1579    }
1580}
1581
1582impl IntoPortable for EnvironmentSpec {
1583    type Output = EnvironmentSpec<PortableForm>;
1584
1585    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1586        EnvironmentSpec {
1587            account_id: self.account_id.into_portable(registry),
1588            balance: self.balance.into_portable(registry),
1589            hash: self.hash.into_portable(registry),
1590            timestamp: self.timestamp.into_portable(registry),
1591            block_number: self.block_number.into_portable(registry),
1592            native_to_eth_ratio: self.native_to_eth_ratio,
1593            trust_backed_assets_precompile_index: self
1594                .trust_backed_assets_precompile_index,
1595            pool_assets_precompile_index: self.pool_assets_precompile_index,
1596            static_buffer_size: self.static_buffer_size,
1597        }
1598    }
1599}
1600
1601impl<F> EnvironmentSpec<F>
1602where
1603    F: Form,
1604    TypeSpec<F>: Default,
1605{
1606    /// Returns the `AccountId` type of the environment.
1607    pub fn account_id(&self) -> &TypeSpec<F> {
1608        &self.account_id
1609    }
1610    /// Returns the `Balance` type of the environment.
1611    pub fn balance(&self) -> &TypeSpec<F> {
1612        &self.balance
1613    }
1614    /// Returns the `Hash` type of the environment.
1615    pub fn hash(&self) -> &TypeSpec<F> {
1616        &self.hash
1617    }
1618    /// Returns the `Timestamp` type of the environment.
1619    pub fn timestamp(&self) -> &TypeSpec<F> {
1620        &self.timestamp
1621    }
1622    /// Returns the `BlockNumber` type of the environment.
1623    pub fn block_number(&self) -> &TypeSpec<F> {
1624        &self.block_number
1625    }
1626    /// Returns the `NATIVE_TO_ETH_RATIO` value of the environment.
1627    pub fn native_to_eth_ratio(&self) -> u32 {
1628        self.native_to_eth_ratio
1629    }
1630    /// Returns the `TRUST_BACKED_ASSETS_PRECOMPILE_INDEX` value of the environment.
1631    pub fn trust_backed_assets_precompile_index(&self) -> u16 {
1632        self.trust_backed_assets_precompile_index
1633    }
1634    /// Returns the `POOL_ASSETS_PRECOMPILE_INDEX` value of the environment.
1635    pub fn pool_assets_precompile_index(&self) -> u16 {
1636        self.pool_assets_precompile_index
1637    }
1638}
1639
1640#[allow(clippy::type_complexity)]
1641impl<F> EnvironmentSpec<F>
1642where
1643    F: Form,
1644    TypeSpec<F>: Default,
1645    EnvironmentSpec<F>: Default,
1646{
1647    pub fn new() -> EnvironmentSpecBuilder<
1648        F,
1649        Missing<state::AccountId>,
1650        Missing<state::Balance>,
1651        Missing<state::Hash>,
1652        Missing<state::Timestamp>,
1653        Missing<state::BlockNumber>,
1654        Missing<state::NativeToEthRatio>,
1655        Missing<state::TrustBackedAssetsPrecompileIndex>,
1656        Missing<state::PoolAssetsPrecompileIndex>,
1657        Missing<state::BufferSize>,
1658    > {
1659        EnvironmentSpecBuilder {
1660            spec: Default::default(),
1661            marker: PhantomData,
1662        }
1663    }
1664}
1665
1666/// An environment specification builder.
1667#[allow(clippy::type_complexity)]
1668#[must_use]
1669pub struct EnvironmentSpecBuilder<F, A, B, H, T, BN, NTER, TBAPI, PAPI, BS>
1670where
1671    F: Form,
1672    TypeSpec<F>: Default,
1673    EnvironmentSpec<F>: Default,
1674{
1675    spec: EnvironmentSpec<F>,
1676    marker: PhantomData<fn() -> (A, B, H, T, BN, NTER, TBAPI, PAPI, BS)>,
1677}
1678
1679impl<F, B, H, T, BN, NTER, TBAPI, PAPI, BS>
1680    EnvironmentSpecBuilder<
1681        F,
1682        Missing<state::AccountId>,
1683        B,
1684        H,
1685        T,
1686        BN,
1687        NTER,
1688        TBAPI,
1689        PAPI,
1690        BS,
1691    >
1692where
1693    F: Form,
1694    TypeSpec<F>: Default,
1695    EnvironmentSpec<F>: Default,
1696{
1697    /// Sets the `AccountId` type of the environment.
1698    pub fn account_id(
1699        self,
1700        account_id: TypeSpec<F>,
1701    ) -> EnvironmentSpecBuilder<F, state::AccountId, B, H, T, BN, NTER, TBAPI, PAPI, BS>
1702    {
1703        EnvironmentSpecBuilder {
1704            spec: EnvironmentSpec {
1705                account_id,
1706                ..self.spec
1707            },
1708            marker: PhantomData,
1709        }
1710    }
1711}
1712
1713impl<F, A, H, T, BN, NTER, TBAPI, PAPI, BS>
1714    EnvironmentSpecBuilder<F, A, Missing<state::Balance>, H, T, BN, NTER, TBAPI, PAPI, BS>
1715where
1716    F: Form,
1717    TypeSpec<F>: Default,
1718    EnvironmentSpec<F>: Default,
1719{
1720    /// Sets the `Balance` type of the environment.
1721    pub fn balance(
1722        self,
1723        balance: TypeSpec<F>,
1724    ) -> EnvironmentSpecBuilder<F, A, state::Balance, H, T, BN, NTER, TBAPI, PAPI, BS>
1725    {
1726        EnvironmentSpecBuilder {
1727            spec: EnvironmentSpec {
1728                balance,
1729                ..self.spec
1730            },
1731            marker: PhantomData,
1732        }
1733    }
1734}
1735
1736impl<F, A, B, T, BN, NTER, TBAPI, PAPI, BS>
1737    EnvironmentSpecBuilder<F, A, B, Missing<state::Hash>, T, BN, NTER, TBAPI, PAPI, BS>
1738where
1739    F: Form,
1740    TypeSpec<F>: Default,
1741    EnvironmentSpec<F>: Default,
1742{
1743    /// Sets the `Hash` type of the environment.
1744    pub fn hash(
1745        self,
1746        hash: TypeSpec<F>,
1747    ) -> EnvironmentSpecBuilder<F, A, B, state::Hash, T, BN, NTER, TBAPI, PAPI, BS> {
1748        EnvironmentSpecBuilder {
1749            spec: EnvironmentSpec { hash, ..self.spec },
1750            marker: PhantomData,
1751        }
1752    }
1753}
1754
1755impl<F, A, B, H, BN, NTER, TBAPI, PAPI, BS>
1756    EnvironmentSpecBuilder<
1757        F,
1758        A,
1759        B,
1760        H,
1761        Missing<state::Timestamp>,
1762        BN,
1763        NTER,
1764        TBAPI,
1765        PAPI,
1766        BS,
1767    >
1768where
1769    F: Form,
1770    TypeSpec<F>: Default,
1771    EnvironmentSpec<F>: Default,
1772{
1773    /// Sets the `Timestamp` type of the environment.
1774    pub fn timestamp(
1775        self,
1776        timestamp: TypeSpec<F>,
1777    ) -> EnvironmentSpecBuilder<F, A, B, H, state::Timestamp, BN, NTER, TBAPI, PAPI, BS>
1778    {
1779        EnvironmentSpecBuilder {
1780            spec: EnvironmentSpec {
1781                timestamp,
1782                ..self.spec
1783            },
1784            marker: PhantomData,
1785        }
1786    }
1787}
1788
1789impl<F, A, B, H, T, NTER, TBAPI, PAPI, BS>
1790    EnvironmentSpecBuilder<
1791        F,
1792        A,
1793        B,
1794        H,
1795        T,
1796        Missing<state::BlockNumber>,
1797        NTER,
1798        TBAPI,
1799        PAPI,
1800        BS,
1801    >
1802where
1803    F: Form,
1804    TypeSpec<F>: Default,
1805    EnvironmentSpec<F>: Default,
1806{
1807    /// Sets the `BlockNumber` type of the environment.
1808    pub fn block_number(
1809        self,
1810        block_number: TypeSpec<F>,
1811    ) -> EnvironmentSpecBuilder<F, A, B, H, T, state::BlockNumber, NTER, TBAPI, PAPI, BS>
1812    {
1813        EnvironmentSpecBuilder {
1814            spec: EnvironmentSpec {
1815                block_number,
1816                ..self.spec
1817            },
1818            marker: PhantomData,
1819        }
1820    }
1821}
1822
1823impl<F, A, B, H, T, BN, PBAPI, PAPI, BS>
1824    EnvironmentSpecBuilder<
1825        F,
1826        A,
1827        B,
1828        H,
1829        T,
1830        BN,
1831        Missing<state::NativeToEthRatio>,
1832        PBAPI,
1833        PAPI,
1834        BS,
1835    >
1836where
1837    F: Form,
1838    TypeSpec<F>: Default,
1839    EnvironmentSpec<F>: Default,
1840{
1841    /// Sets the `NATIVE_TO_ETH_RATIO` value of the environment.
1842    pub fn native_to_eth_ratio(
1843        self,
1844        native_to_eth_ratio: u32,
1845    ) -> EnvironmentSpecBuilder<F, A, B, H, T, BN, state::NativeToEthRatio, PBAPI, PAPI, BS>
1846    {
1847        EnvironmentSpecBuilder {
1848            spec: EnvironmentSpec {
1849                native_to_eth_ratio,
1850                ..self.spec
1851            },
1852            marker: PhantomData,
1853        }
1854    }
1855}
1856
1857impl<F, A, B, H, T, BN, NTER, PAPI, BS>
1858    EnvironmentSpecBuilder<
1859        F,
1860        A,
1861        B,
1862        H,
1863        T,
1864        BN,
1865        NTER,
1866        Missing<state::TrustBackedAssetsPrecompileIndex>,
1867        PAPI,
1868        BS,
1869    >
1870where
1871    F: Form,
1872    TypeSpec<F>: Default,
1873    EnvironmentSpec<F>: Default,
1874{
1875    /// Sets the `TRUST_BACKED_ASSETS_PRECOMPILE_INDEX` value of the environment.
1876    pub fn trust_backed_assets_precompile_index(
1877        self,
1878        trust_backed_assets_precompile_index: u16,
1879    ) -> EnvironmentSpecBuilder<
1880        F,
1881        A,
1882        B,
1883        H,
1884        T,
1885        BN,
1886        NTER,
1887        state::TrustBackedAssetsPrecompileIndex,
1888        PAPI,
1889        BS,
1890    > {
1891        EnvironmentSpecBuilder {
1892            spec: EnvironmentSpec {
1893                trust_backed_assets_precompile_index,
1894                ..self.spec
1895            },
1896            marker: PhantomData,
1897        }
1898    }
1899}
1900
1901impl<F, A, B, H, T, BN, NTER, TBAPI, BS>
1902    EnvironmentSpecBuilder<
1903        F,
1904        A,
1905        B,
1906        H,
1907        T,
1908        BN,
1909        NTER,
1910        TBAPI,
1911        Missing<state::PoolAssetsPrecompileIndex>,
1912        BS,
1913    >
1914where
1915    F: Form,
1916    TypeSpec<F>: Default,
1917    EnvironmentSpec<F>: Default,
1918{
1919    /// Sets the `POOL_ASSETS_PRECOMPILE_INDEX` value of the environment.
1920    pub fn pool_assets_precompile_index(
1921        self,
1922        pool_assets_precompile_index: u16,
1923    ) -> EnvironmentSpecBuilder<
1924        F,
1925        A,
1926        B,
1927        H,
1928        T,
1929        BN,
1930        NTER,
1931        TBAPI,
1932        state::PoolAssetsPrecompileIndex,
1933        BS,
1934    > {
1935        EnvironmentSpecBuilder {
1936            spec: EnvironmentSpec {
1937                pool_assets_precompile_index,
1938                ..self.spec
1939            },
1940            marker: PhantomData,
1941        }
1942    }
1943}
1944
1945impl<F, A, B, H, T, BN, NTER, TBAPI, PAPI>
1946    EnvironmentSpecBuilder<
1947        F,
1948        A,
1949        B,
1950        H,
1951        T,
1952        BN,
1953        NTER,
1954        TBAPI,
1955        PAPI,
1956        Missing<state::BufferSize>,
1957    >
1958where
1959    F: Form,
1960    TypeSpec<F>: Default,
1961    EnvironmentSpec<F>: Default,
1962{
1963    /// Sets the size of the static buffer configured via environment variable.`
1964    pub fn static_buffer_size(
1965        self,
1966        static_buffer_size: usize,
1967    ) -> EnvironmentSpecBuilder<F, A, B, H, T, BN, NTER, TBAPI, PAPI, state::BufferSize>
1968    {
1969        EnvironmentSpecBuilder {
1970            spec: EnvironmentSpec {
1971                static_buffer_size,
1972                ..self.spec
1973            },
1974            marker: PhantomData,
1975        }
1976    }
1977}
1978
1979impl<F>
1980    EnvironmentSpecBuilder<
1981        F,
1982        state::AccountId,
1983        state::Balance,
1984        state::Hash,
1985        state::Timestamp,
1986        state::BlockNumber,
1987        state::NativeToEthRatio,
1988        state::TrustBackedAssetsPrecompileIndex,
1989        state::PoolAssetsPrecompileIndex,
1990        state::BufferSize,
1991    >
1992where
1993    F: Form,
1994    TypeSpec<F>: Default,
1995    EnvironmentSpec<F>: Default,
1996{
1997    /// Finished constructing the `EnvironmentSpec` object.
1998    pub fn done(self) -> EnvironmentSpec<F> {
1999        self.spec
2000    }
2001}