concordium_rust_sdk/v2/
conversions.rs

1//! Helpers and trait implementations to convert from proto generated types to
2//! their Rust equivalents.
3
4use super::{generated::*, Require};
5use crate::{
6    types::{
7        queries::ConcordiumBFTDetails, AccountReleaseSchedule, ActiveBakerPoolStatus,
8        UpdateKeysCollectionSkeleton,
9    },
10    v2::generated::{block_item_summary::Details, BlockCertificates},
11};
12use chrono::TimeZone;
13use concordium_base::{
14    base,
15    common::{Deserial, Versioned, VERSION_0},
16    id::{
17        constants::{ArCurve, AttributeKind, IpPairing},
18        types::{
19            AccountCredentialWithoutProofs, CredentialDeploymentValues,
20            InitialCredentialDeploymentValues,
21        },
22    },
23    updates,
24};
25use cooldown::CooldownStatus;
26use std::collections::{BTreeMap, BTreeSet};
27
28fn consume<A: Deserial>(bytes: &[u8]) -> Result<A, tonic::Status> {
29    let mut cursor = std::io::Cursor::new(bytes);
30    let res = A::deserial(&mut cursor);
31    match res {
32        Ok(v) if cursor.position() == bytes.len() as u64 => Ok(v),
33        _ => Err(tonic::Status::internal(
34            "Unexpected response from the server.",
35        )),
36    }
37}
38
39impl TryFrom<AccountAddress> for super::AccountAddress {
40    type Error = tonic::Status;
41
42    fn try_from(value: AccountAddress) -> Result<Self, Self::Error> {
43        match value.value.try_into() {
44            Ok(addr) => Ok(Self(addr)),
45            Err(_) => Err(tonic::Status::internal(
46                "Unexpected account address format.",
47            )),
48        }
49    }
50}
51
52impl From<super::ContractAddress> for ContractAddress {
53    fn from(value: super::ContractAddress) -> Self {
54        Self {
55            index:    value.index,
56            subindex: value.subindex,
57        }
58    }
59}
60
61impl TryFrom<Address> for super::types::Address {
62    type Error = tonic::Status;
63
64    fn try_from(value: Address) -> Result<Self, Self::Error> {
65        match value.r#type.require()? {
66            address::Type::Account(acc) => Ok(Self::Account(acc.try_into()?)),
67            address::Type::Contract(contr) => Ok(Self::Contract(contr.into())),
68        }
69    }
70}
71
72impl TryFrom<ModuleRef> for super::ModuleReference {
73    type Error = tonic::Status;
74
75    fn try_from(value: ModuleRef) -> Result<Self, Self::Error> {
76        match value.value.try_into() {
77            Ok(mod_ref) => Ok(Self::new(mod_ref)),
78            Err(_) => Err(tonic::Status::internal(
79                "Unexpected module reference format.",
80            )),
81        }
82    }
83}
84
85impl From<ContractAddress> for super::ContractAddress {
86    fn from(value: ContractAddress) -> Self {
87        super::ContractAddress::new(value.index, value.subindex)
88    }
89}
90
91impl From<Slot> for super::types::Slot {
92    fn from(value: Slot) -> Self { super::types::Slot { slot: value.value } }
93}
94
95impl TryFrom<VersionedModuleSource> for super::types::smart_contracts::WasmModule {
96    type Error = tonic::Status;
97
98    fn try_from(versioned_module: VersionedModuleSource) -> Result<Self, Self::Error> {
99        use super::types::smart_contracts::WasmVersion;
100        let module = match versioned_module.module.require()? {
101            versioned_module_source::Module::V0(versioned_module_source::ModuleSourceV0 {
102                value,
103            }) => super::types::smart_contracts::WasmModule {
104                version: WasmVersion::V0,
105                source:  value.into(),
106            },
107            versioned_module_source::Module::V1(versioned_module_source::ModuleSourceV1 {
108                value,
109            }) => super::types::smart_contracts::WasmModule {
110                version: WasmVersion::V1,
111                source:  value.into(),
112            },
113        };
114        Ok(module)
115    }
116}
117
118impl TryFrom<Parameter> for super::types::smart_contracts::OwnedParameter {
119    type Error = tonic::Status;
120
121    fn try_from(value: Parameter) -> Result<Self, Self::Error> {
122        Self::try_from(value.value).map_err(
123            |e: concordium_base::smart_contracts::ExceedsParameterSize| {
124                tonic::Status::invalid_argument(e.to_string())
125            },
126        )
127    }
128}
129
130impl TryFrom<InstanceInfo> for super::InstanceInfo {
131    type Error = tonic::Status;
132
133    fn try_from(value: InstanceInfo) -> Result<Self, Self::Error> {
134        match value.version.require()? {
135            instance_info::Version::V0(v0) => Ok(Self::V0 {
136                model:         v0.model.require()?.value,
137                owner:         v0.owner.require()?.try_into()?,
138                amount:        v0.amount.require()?.into(),
139                methods:       v0
140                    .methods
141                    .into_iter()
142                    .map(TryFrom::try_from)
143                    .collect::<Result<_, tonic::Status>>()?,
144                name:          v0.name.require()?.try_into()?,
145                source_module: v0.source_module.require()?.try_into()?,
146            }),
147            instance_info::Version::V1(v1) => Ok(Self::V1 {
148                owner:         v1.owner.require()?.try_into()?,
149                amount:        v1.amount.require()?.into(),
150                methods:       v1
151                    .methods
152                    .into_iter()
153                    .map(TryFrom::try_from)
154                    .collect::<Result<_, tonic::Status>>()?,
155                name:          v1.name.require()?.try_into()?,
156                source_module: v1.source_module.require()?.try_into()?,
157            }),
158        }
159    }
160}
161
162impl TryFrom<ReceiveName> for concordium_base::contracts_common::OwnedReceiveName {
163    type Error = tonic::Status;
164
165    fn try_from(value: ReceiveName) -> Result<Self, Self::Error> {
166        match Self::new(value.value) {
167            Ok(rn) => Ok(rn),
168            Err(_) => Err(tonic::Status::internal("Unexpected receive name format.")),
169        }
170    }
171}
172
173impl TryFrom<InitName> for concordium_base::contracts_common::OwnedContractName {
174    type Error = tonic::Status;
175
176    fn try_from(value: InitName) -> Result<Self, Self::Error> {
177        match Self::new(value.value) {
178            Ok(cn) => Ok(cn),
179            Err(_) => Err(tonic::Status::internal("Unexpected contract name format.")),
180        }
181    }
182}
183
184impl TryFrom<BlockHash> for super::BlockHash {
185    type Error = tonic::Status;
186
187    fn try_from(value: BlockHash) -> Result<Self, Self::Error> {
188        match value.value.try_into() {
189            Ok(hash) => Ok(Self::new(hash)),
190            Err(_) => Err(tonic::Status::internal("Unexpected block hash format.")),
191        }
192    }
193}
194
195impl TryFrom<TransactionHash> for super::hashes::TransactionHash {
196    type Error = tonic::Status;
197
198    fn try_from(value: TransactionHash) -> Result<Self, Self::Error> {
199        match value.value.try_into() {
200            Ok(hash) => Ok(Self::new(hash)),
201            Err(_) => Err(tonic::Status::internal(
202                "Unexpected transaction hash format.",
203            )),
204        }
205    }
206}
207
208impl TryFrom<AccountTransactionSignHash> for super::hashes::TransactionSignHash {
209    type Error = tonic::Status;
210
211    fn try_from(value: AccountTransactionSignHash) -> Result<Self, Self::Error> {
212        match value.value.try_into() {
213            Ok(hash) => Ok(Self::new(hash)),
214            Err(_) => Err(tonic::Status::internal(
215                "Unexpected account transaction sign hash format.",
216            )),
217        }
218    }
219}
220
221impl TryFrom<Sha256Hash> for super::hashes::Hash {
222    type Error = tonic::Status;
223
224    fn try_from(value: Sha256Hash) -> Result<Self, Self::Error> {
225        match value.value.try_into() {
226            Ok(hash) => Ok(Self::new(hash)),
227            Err(_) => Err(tonic::Status::internal("Unexpected hash format.")),
228        }
229    }
230}
231
232impl TryFrom<StateHash> for super::hashes::StateHash {
233    type Error = tonic::Status;
234
235    fn try_from(value: StateHash) -> Result<Self, Self::Error> {
236        match value.value.try_into() {
237            Ok(hash) => Ok(Self::new(hash)),
238            Err(_) => Err(tonic::Status::internal("Unexpected state hash format.")),
239        }
240    }
241}
242
243impl TryFrom<LeadershipElectionNonce> for super::hashes::LeadershipElectionNonce {
244    type Error = tonic::Status;
245
246    fn try_from(value: LeadershipElectionNonce) -> Result<Self, Self::Error> {
247        match value.value.try_into() {
248            Ok(hash) => Ok(Self::new(hash)),
249            Err(_) => Err(tonic::Status::internal(
250                "Unexpected leadership election nonce format.",
251            )),
252        }
253    }
254}
255
256impl From<AbsoluteBlockHeight> for super::AbsoluteBlockHeight {
257    fn from(abh: AbsoluteBlockHeight) -> Self { Self { height: abh.value } }
258}
259
260impl From<BlockHeight> for super::types::BlockHeight {
261    fn from(bh: BlockHeight) -> Self { Self { height: bh.value } }
262}
263
264impl From<super::AbsoluteBlockHeight> for AbsoluteBlockHeight {
265    fn from(abh: super::AbsoluteBlockHeight) -> Self { Self { value: abh.height } }
266}
267
268impl From<super::RelativeBlockHeight> for block_hash_input::RelativeHeight {
269    fn from(relative_block_height: super::RelativeBlockHeight) -> Self {
270        Self {
271            genesis_index: Some(relative_block_height.genesis_index.into()),
272            height:        Some(relative_block_height.height.into()),
273            restrict:      relative_block_height.restrict,
274        }
275    }
276}
277
278impl From<super::types::BlockHeight> for BlockHeight {
279    fn from(bh: super::types::BlockHeight) -> Self { Self { value: bh.height } }
280}
281
282impl From<SequenceNumber> for super::types::Nonce {
283    fn from(n: SequenceNumber) -> Self { Self { nonce: n.value } }
284}
285
286impl From<Amount> for super::super::common::types::Amount {
287    fn from(n: Amount) -> Self { Self { micro_ccd: n.value } }
288}
289
290impl From<AccountIndex> for super::types::AccountIndex {
291    fn from(n: AccountIndex) -> Self { Self { index: n.value } }
292}
293
294impl From<super::types::AccountIndex> for AccountIndex {
295    fn from(n: super::types::AccountIndex) -> Self { Self { value: n.index } }
296}
297
298impl From<BakerId> for super::types::BakerId {
299    fn from(n: BakerId) -> Self { Self { id: n.value.into() } }
300}
301
302impl From<super::types::BakerId> for BakerId {
303    fn from(n: super::types::BakerId) -> Self { Self { value: n.id.into() } }
304}
305
306impl TryFrom<DelegationTarget> for super::types::DelegationTarget {
307    type Error = tonic::Status;
308
309    fn try_from(dt: DelegationTarget) -> Result<Self, Self::Error> {
310        match dt.target.require()? {
311            delegation_target::Target::Passive(_) => Ok(Self::Passive),
312            delegation_target::Target::Baker(bid) => Ok(Self::Baker {
313                baker_id: bid.into(),
314            }),
315        }
316    }
317}
318
319impl TryFrom<EncryptionKey> for crate::id::elgamal::PublicKey<ArCurve> {
320    type Error = tonic::Status;
321
322    fn try_from(value: EncryptionKey) -> Result<Self, Self::Error> { consume(&value.value) }
323}
324
325impl TryFrom<ar_info::ArPublicKey> for crate::id::elgamal::PublicKey<ArCurve> {
326    type Error = tonic::Status;
327
328    fn try_from(value: ar_info::ArPublicKey) -> Result<Self, Self::Error> { consume(&value.value) }
329}
330
331impl TryFrom<AccountThreshold> for super::types::AccountThreshold {
332    type Error = tonic::Status;
333
334    fn try_from(value: AccountThreshold) -> Result<Self, Self::Error> {
335        if let Ok(Ok(v)) = u8::try_from(value.value).map(Self::try_from) {
336            Ok(v)
337        } else {
338            Err(tonic::Status::internal("Unexpected account threshold."))
339        }
340    }
341}
342
343impl TryFrom<EncryptedAmount> for crate::encrypted_transfers::types::EncryptedAmount<ArCurve> {
344    type Error = tonic::Status;
345
346    fn try_from(value: EncryptedAmount) -> Result<Self, Self::Error> { consume(&value.value) }
347}
348
349impl TryFrom<BakerElectionVerifyKey> for super::types::BakerElectionVerifyKey {
350    type Error = tonic::Status;
351
352    fn try_from(value: BakerElectionVerifyKey) -> Result<Self, Self::Error> {
353        consume(&value.value)
354    }
355}
356
357impl TryFrom<BakerSignatureVerifyKey> for super::types::BakerSignatureVerifyKey {
358    type Error = tonic::Status;
359
360    fn try_from(value: BakerSignatureVerifyKey) -> Result<Self, Self::Error> {
361        consume(&value.value)
362    }
363}
364
365impl TryFrom<BakerAggregationVerifyKey> for super::types::BakerAggregationVerifyKey {
366    type Error = tonic::Status;
367
368    fn try_from(value: BakerAggregationVerifyKey) -> Result<Self, Self::Error> {
369        consume(&value.value)
370    }
371}
372
373impl TryFrom<EncryptedBalance> for super::types::AccountEncryptedAmount {
374    type Error = tonic::Status;
375
376    fn try_from(value: EncryptedBalance) -> Result<Self, Self::Error> {
377        let self_amount = value.self_amount.require()?.try_into()?;
378        let start_index = value.start_index;
379        let aggregated_amount = match (value.aggregated_amount, value.num_aggregated) {
380            (Some(aa), Some(si)) => Some((aa.try_into()?, si)),
381            (None, None) => None,
382            _ => {
383                return Err(tonic::Status::internal(
384                    "Unexpected response for 'EncryptedBalance'.",
385                ))
386            }
387        };
388        let incoming_amounts = value
389            .incoming_amounts
390            .into_iter()
391            .map(TryFrom::try_from)
392            .collect::<Result<_, tonic::Status>>()?;
393        Ok(Self {
394            self_amount,
395            start_index,
396            aggregated_amount,
397            incoming_amounts,
398        })
399    }
400}
401
402impl TryFrom<Duration> for chrono::Duration {
403    type Error = tonic::Status;
404
405    fn try_from(value: Duration) -> Result<Self, Self::Error> {
406        chrono::TimeDelta::try_milliseconds(value.value as i64).ok_or_else(|| {
407            tonic::Status::internal("Unexpected response for 'Duration': Duration out of bounds.")
408        })
409    }
410}
411
412impl From<Duration> for super::types::SlotDuration {
413    fn from(value: Duration) -> Self {
414        super::types::SlotDuration {
415            millis: value.value,
416        }
417    }
418}
419
420impl From<Duration> for concordium_base::contracts_common::Duration {
421    fn from(value: Duration) -> Self {
422        concordium_base::contracts_common::Duration::from_millis(value.value)
423    }
424}
425
426impl From<GenesisIndex> for super::types::GenesisIndex {
427    fn from(value: GenesisIndex) -> Self { value.value.into() }
428}
429
430impl From<super::types::GenesisIndex> for GenesisIndex {
431    fn from(value: super::types::GenesisIndex) -> Self {
432        GenesisIndex {
433            value: value.into(),
434        }
435    }
436}
437
438impl From<ProtocolVersion> for super::types::ProtocolVersion {
439    fn from(value: ProtocolVersion) -> Self {
440        match value {
441            ProtocolVersion::ProtocolVersion1 => super::types::ProtocolVersion::P1,
442            ProtocolVersion::ProtocolVersion2 => super::types::ProtocolVersion::P2,
443            ProtocolVersion::ProtocolVersion3 => super::types::ProtocolVersion::P3,
444            ProtocolVersion::ProtocolVersion4 => super::types::ProtocolVersion::P4,
445            ProtocolVersion::ProtocolVersion5 => super::types::ProtocolVersion::P5,
446            ProtocolVersion::ProtocolVersion6 => super::types::ProtocolVersion::P6,
447            ProtocolVersion::ProtocolVersion7 => super::types::ProtocolVersion::P7,
448            ProtocolVersion::ProtocolVersion8 => super::types::ProtocolVersion::P8,
449            ProtocolVersion::ProtocolVersion9 => super::types::ProtocolVersion::P9,
450        }
451    }
452}
453
454impl From<super::types::ProtocolVersion> for ProtocolVersion {
455    fn from(value: super::types::ProtocolVersion) -> Self {
456        match value {
457            super::types::ProtocolVersion::P1 => ProtocolVersion::ProtocolVersion1,
458            super::types::ProtocolVersion::P2 => ProtocolVersion::ProtocolVersion2,
459            super::types::ProtocolVersion::P3 => ProtocolVersion::ProtocolVersion3,
460            super::types::ProtocolVersion::P4 => ProtocolVersion::ProtocolVersion4,
461            super::types::ProtocolVersion::P5 => ProtocolVersion::ProtocolVersion5,
462            super::types::ProtocolVersion::P6 => ProtocolVersion::ProtocolVersion6,
463            super::types::ProtocolVersion::P7 => ProtocolVersion::ProtocolVersion7,
464            super::types::ProtocolVersion::P8 => ProtocolVersion::ProtocolVersion8,
465            super::types::ProtocolVersion::P9 => ProtocolVersion::ProtocolVersion9,
466        }
467    }
468}
469
470impl TryFrom<StakePendingChange> for super::types::StakePendingChange {
471    type Error = tonic::Status;
472
473    fn try_from(value: StakePendingChange) -> Result<Self, Self::Error> {
474        match value.change.require()? {
475            stake_pending_change::Change::Reduce(rs) => Ok(Self::ReduceStake {
476                new_stake:      rs.new_stake.require()?.into(),
477                effective_time: rs.effective_time.require()?.try_into()?,
478            }),
479            stake_pending_change::Change::Remove(rs) => {
480                let effective_time = rs.try_into()?;
481                Ok(Self::RemoveStake { effective_time })
482            }
483        }
484    }
485}
486
487impl TryFrom<BakerInfo> for super::types::BakerInfo {
488    type Error = tonic::Status;
489
490    fn try_from(value: BakerInfo) -> Result<Self, Self::Error> {
491        Ok(Self {
492            baker_id:                     value.baker_id.require()?.into(),
493            baker_election_verify_key:    value.election_key.require()?.try_into()?,
494            baker_signature_verify_key:   value.signature_key.require()?.try_into()?,
495            baker_aggregation_verify_key: value.aggregation_key.require()?.try_into()?,
496        })
497    }
498}
499
500impl From<OpenStatus> for super::types::OpenStatus {
501    fn from(os: OpenStatus) -> Self {
502        match os {
503            OpenStatus::OpenForAll => Self::OpenForAll,
504            OpenStatus::ClosedForNew => Self::ClosedForNew,
505            OpenStatus::ClosedForAll => Self::ClosedForAll,
506        }
507    }
508}
509
510impl From<AmountFraction> for super::types::AmountFraction {
511    fn from(af: AmountFraction) -> Self { Self::new_unchecked(af.parts_per_hundred_thousand) }
512}
513
514impl From<AmountFraction> for super::types::PartsPerHundredThousands {
515    fn from(af: AmountFraction) -> Self { Self::new_unchecked(af.parts_per_hundred_thousand) }
516}
517
518impl TryFrom<CommissionRates> for super::types::CommissionRates {
519    type Error = tonic::Status;
520
521    fn try_from(value: CommissionRates) -> Result<Self, Self::Error> {
522        Ok(Self {
523            finalization: value.finalization.require()?.into(),
524            baking:       value.baking.require()?.into(),
525            transaction:  value.transaction.require()?.into(),
526        })
527    }
528}
529
530impl TryFrom<BakerPoolInfo> for super::types::BakerPoolInfo {
531    type Error = tonic::Status;
532
533    fn try_from(value: BakerPoolInfo) -> Result<Self, Self::Error> {
534        let open_status = value.open_status().into();
535        let metadata_url = value
536            .url
537            .try_into()
538            .map_err(|_| tonic::Status::internal("Unexpected metadata length."))?;
539        let commission_rates = value.commission_rates.require()?.try_into()?;
540        Ok(Self {
541            open_status,
542            metadata_url,
543            commission_rates,
544        })
545    }
546}
547
548impl TryFrom<AccountStakingInfo> for super::types::AccountStakingInfo {
549    type Error = tonic::Status;
550
551    fn try_from(value: AccountStakingInfo) -> Result<Self, Self::Error> {
552        match value.staking_info.require()? {
553            account_staking_info::StakingInfo::Baker(bsi) => {
554                let staked_amount = bsi.staked_amount.require()?.into();
555                let restake_earnings = bsi.restake_earnings;
556                let baker_info = bsi.baker_info.require()?.try_into()?;
557                let pending_change = match bsi.pending_change {
558                    None => None,
559                    Some(pc) => Some(pc.try_into()?),
560                };
561                let pool_info = match bsi.pool_info {
562                    None => None,
563                    Some(bi) => Some(bi.try_into()?),
564                };
565                let is_suspended = bsi.is_suspended;
566                Ok(Self::Baker {
567                    staked_amount,
568                    restake_earnings,
569                    baker_info: Box::new(baker_info),
570                    pending_change,
571                    pool_info,
572                    is_suspended,
573                })
574            }
575            account_staking_info::StakingInfo::Delegator(dsi) => {
576                let staked_amount = dsi.staked_amount.require()?.into();
577                let restake_earnings = dsi.restake_earnings;
578                let delegation_target = dsi.target.require()?.try_into()?;
579                let pending_change = match dsi.pending_change {
580                    None => None,
581                    Some(pc) => Some(pc.try_into()?),
582                };
583                Ok(Self::Delegated {
584                    staked_amount,
585                    restake_earnings,
586                    delegation_target,
587                    pending_change,
588                })
589            }
590        }
591    }
592}
593
594impl TryFrom<Release> for super::types::Release {
595    type Error = tonic::Status;
596
597    fn try_from(value: Release) -> Result<Self, Self::Error> {
598        Ok(Self {
599            timestamp:    value.timestamp.require()?.try_into()?,
600            amount:       value.amount.require()?.into(),
601            transactions: value
602                .transactions
603                .into_iter()
604                .map(TryFrom::try_from)
605                .collect::<Result<_, tonic::Status>>()?,
606        })
607    }
608}
609
610impl TryFrom<ReleaseSchedule> for super::types::AccountReleaseSchedule {
611    type Error = tonic::Status;
612
613    fn try_from(value: ReleaseSchedule) -> Result<Self, Self::Error> {
614        Ok(Self {
615            total:    value.total.require()?.into(),
616            schedule: value
617                .schedules
618                .into_iter()
619                .map(TryFrom::try_from)
620                .collect::<Result<_, tonic::Status>>()?,
621        })
622    }
623}
624
625impl TryFrom<AccountVerifyKey> for crate::id::types::VerifyKey {
626    type Error = tonic::Status;
627
628    fn try_from(value: AccountVerifyKey) -> Result<Self, Self::Error> {
629        match value.key.require()? {
630            account_verify_key::Key::Ed25519Key(v) => Ok(Self::Ed25519VerifyKey(consume(&v)?)),
631        }
632    }
633}
634
635impl TryFrom<ip_info::IpCdiVerifyKey> for ed25519_dalek::VerifyingKey {
636    type Error = tonic::Status;
637
638    fn try_from(value: ip_info::IpCdiVerifyKey) -> Result<Self, Self::Error> {
639        consume(&value.value)
640    }
641}
642
643impl TryFrom<ip_info::IpVerifyKey> for crate::id::ps_sig::PublicKey<IpPairing> {
644    type Error = tonic::Status;
645
646    fn try_from(value: ip_info::IpVerifyKey) -> Result<Self, Self::Error> { consume(&value.value) }
647}
648
649impl TryFrom<UpdatePublicKey> for super::types::UpdatePublicKey {
650    type Error = tonic::Status;
651
652    fn try_from(value: UpdatePublicKey) -> Result<Self, Self::Error> {
653        Ok(super::types::UpdatePublicKey {
654            public: crate::id::types::VerifyKey::Ed25519VerifyKey(consume(&value.value)?),
655        })
656    }
657}
658
659impl TryFrom<SignatureThreshold> for crate::id::types::SignatureThreshold {
660    type Error = tonic::Status;
661
662    fn try_from(value: SignatureThreshold) -> Result<Self, Self::Error> {
663        if let Ok(v) = u8::try_from(value.value) {
664            crate::id::types::SignatureThreshold::try_from(v)
665                .map_err(|_| tonic::Status::internal("Unexpected zero signature threshold."))
666        } else {
667            Err(tonic::Status::internal("Unexpected signature threshold."))
668        }
669    }
670}
671
672impl TryFrom<ArThreshold> for crate::id::secret_sharing::Threshold {
673    type Error = tonic::Status;
674
675    fn try_from(value: ArThreshold) -> Result<Self, Self::Error> {
676        if let Ok(v) = u8::try_from(value.value) {
677            if v == 0 {
678                Err(tonic::Status::internal("Unexpected zero AR threshold."))
679            } else {
680                Ok(Self(v))
681            }
682        } else {
683            Err(tonic::Status::internal("Unexpected AR threshold."))
684        }
685    }
686}
687
688impl TryFrom<CredentialPublicKeys> for crate::id::types::CredentialPublicKeys {
689    type Error = tonic::Status;
690
691    fn try_from(value: CredentialPublicKeys) -> Result<Self, Self::Error> {
692        Ok(Self {
693            keys:      value
694                .keys
695                .into_iter()
696                .map(|(k, v)| {
697                    if let Ok(k) = u8::try_from(k) {
698                        let k = k.into();
699                        let v = v.try_into()?;
700                        Ok((k, v))
701                    } else {
702                        Err(tonic::Status::internal("Unexpected key index."))
703                    }
704                })
705                .collect::<Result<_, tonic::Status>>()?,
706            threshold: value.threshold.require()?.try_into()?,
707        })
708    }
709}
710
711impl TryFrom<CredentialRegistrationId> for super::types::CredentialRegistrationID {
712    type Error = tonic::Status;
713
714    fn try_from(value: CredentialRegistrationId) -> Result<Self, Self::Error> {
715        consume(&value.value)
716    }
717}
718
719impl TryFrom<CredentialRegistrationId> for ArCurve {
720    type Error = tonic::Status;
721
722    fn try_from(value: CredentialRegistrationId) -> Result<Self, Self::Error> {
723        consume(&value.value)
724    }
725}
726
727impl From<IdentityProviderIdentity> for crate::id::types::IpIdentity {
728    fn from(v: IdentityProviderIdentity) -> Self { Self(v.value) }
729}
730
731impl TryFrom<YearMonth> for crate::id::types::YearMonth {
732    type Error = tonic::Status;
733
734    fn try_from(value: YearMonth) -> Result<Self, Self::Error> {
735        Ok(Self {
736            year:  value
737                .year
738                .try_into()
739                .map_err(|_| tonic::Status::internal("Unexpected year."))?,
740            month: value
741                .month
742                .try_into()
743                .map_err(|_| tonic::Status::internal("Unexpected year."))?,
744        })
745    }
746}
747
748impl TryFrom<Policy> for crate::id::types::Policy<ArCurve, AttributeKind> {
749    type Error = tonic::Status;
750
751    fn try_from(value: Policy) -> Result<Self, Self::Error> {
752        Ok(Self {
753            valid_to:   value.valid_to.require()?.try_into()?,
754            created_at: value.created_at.require()?.try_into()?,
755            policy_vec: value
756                .attributes
757                .into_iter()
758                .map(|(k, v)| {
759                    let k = crate::id::types::AttributeTag(
760                        k.try_into()
761                            .map_err(|_| tonic::Status::internal("Unexpected attribute tag."))?,
762                    );
763                    let v = AttributeKind(String::from_utf8(v).map_err(|_| {
764                        tonic::Status::internal("Invalid attribute value. Expected UTF8 encoding")
765                    })?);
766                    Ok((k, v))
767                })
768                .collect::<Result<_, tonic::Status>>()?,
769            _phantom:   std::marker::PhantomData,
770        })
771    }
772}
773
774impl TryFrom<ChainArData> for crate::id::types::ChainArData<ArCurve> {
775    type Error = tonic::Status;
776
777    fn try_from(value: ChainArData) -> Result<Self, Self::Error> {
778        consume(&value.enc_id_cred_pub_share)
779    }
780}
781
782impl TryFrom<Commitment> for crate::id::pedersen_commitment::Commitment<ArCurve> {
783    type Error = tonic::Status;
784
785    fn try_from(value: Commitment) -> Result<Self, Self::Error> { consume(&value.value) }
786}
787
788impl TryFrom<CredentialCommitments> for crate::id::types::CredentialDeploymentCommitments<ArCurve> {
789    type Error = tonic::Status;
790
791    fn try_from(value: CredentialCommitments) -> Result<Self, Self::Error> {
792        Ok(Self {
793            cmm_prf: value.prf.require()?.try_into()?,
794            cmm_cred_counter: value.cred_counter.require()?.try_into()?,
795            cmm_max_accounts: value.max_accounts.require()?.try_into()?,
796            cmm_attributes: value
797                .attributes
798                .into_iter()
799                .map(|(k, v)| {
800                    let k = crate::id::types::AttributeTag(
801                        k.try_into()
802                            .map_err(|_| tonic::Status::internal("Unexpected attribute tag."))?,
803                    );
804                    let v = v.try_into()?;
805                    Ok((k, v))
806                })
807                .collect::<Result<_, tonic::Status>>()?,
808            cmm_id_cred_sec_sharing_coeff: value
809                .id_cred_sec_sharing_coeff
810                .into_iter()
811                .map(TryFrom::try_from)
812                .collect::<Result<_, tonic::Status>>()?,
813        })
814    }
815}
816
817impl TryFrom<AccountCredential> for AccountCredentialWithoutProofs<ArCurve, AttributeKind> {
818    type Error = tonic::Status;
819
820    fn try_from(value: AccountCredential) -> Result<Self, Self::Error> {
821        match value.credential_values.require()? {
822            account_credential::CredentialValues::Initial(ic) => {
823                let icdv = InitialCredentialDeploymentValues {
824                    cred_account: ic.keys.require()?.try_into()?,
825                    reg_id:       ic.cred_id.require()?.try_into()?,
826                    ip_identity:  ic.ip_id.require()?.into(),
827                    policy:       ic.policy.require()?.try_into()?,
828                };
829                Ok(Self::Initial { icdv })
830            }
831            account_credential::CredentialValues::Normal(nc) => {
832                let cdv = CredentialDeploymentValues {
833                    cred_key_info: nc.keys.require()?.try_into()?,
834                    cred_id:       nc.cred_id.require()?.try_into()?,
835                    ip_identity:   nc.ip_id.require()?.into(),
836                    threshold:     nc.ar_threshold.require()?.try_into()?,
837                    ar_data:       nc
838                        .ar_data
839                        .into_iter()
840                        .map(|(k, v)| {
841                            let k = k
842                                .try_into()
843                                .map_err(|_| tonic::Status::internal("Unexpected AR identity."))?;
844                            let v = v.try_into()?;
845                            Ok((k, v))
846                        })
847                        .collect::<Result<_, tonic::Status>>()?,
848                    policy:        nc.policy.require()?.try_into()?,
849                };
850                let commitments = nc.commitments.require()?.try_into()?;
851                Ok(Self::Normal { cdv, commitments })
852            }
853        }
854    }
855}
856
857impl From<Timestamp> for concordium_base::common::types::Timestamp {
858    fn from(value: Timestamp) -> Self { value.value.into() }
859}
860
861impl From<concordium_base::common::types::Timestamp> for Timestamp {
862    fn from(value: concordium_base::common::types::Timestamp) -> Self {
863        Timestamp {
864            value: value.millis,
865        }
866    }
867}
868
869impl TryFrom<Timestamp> for chrono::DateTime<chrono::Utc> {
870    type Error = tonic::Status;
871
872    fn try_from(value: Timestamp) -> Result<Self, Self::Error> {
873        let ts = chrono::Utc.timestamp_millis_opt(
874            value
875                .value
876                .try_into()
877                .map_err(|_| tonic::Status::internal("Timestamp out of range."))?,
878        );
879        ts.single()
880            .ok_or_else(|| tonic::Status::internal("Ambiguous time."))
881    }
882}
883
884impl TryFrom<DelegatorInfo> for super::types::DelegatorInfo {
885    type Error = tonic::Status;
886
887    fn try_from(delegator: DelegatorInfo) -> Result<Self, Self::Error> {
888        Ok(Self {
889            account:        delegator.account.require()?.try_into()?,
890            stake:          delegator.stake.require()?.into(),
891            pending_change: delegator
892                .pending_change
893                .map(TryFrom::try_from)
894                .transpose()?,
895        })
896    }
897}
898
899impl TryFrom<DelegatorRewardPeriodInfo> for super::types::DelegatorRewardPeriodInfo {
900    type Error = tonic::Status;
901
902    fn try_from(delegator: DelegatorRewardPeriodInfo) -> Result<Self, Self::Error> {
903        Ok(Self {
904            account: delegator.account.require()?.try_into()?,
905            stake:   delegator.stake.require()?.into(),
906        })
907    }
908}
909
910impl From<CooldownStatus> for super::types::CooldownStatus {
911    fn from(cds: CooldownStatus) -> Self {
912        match cds {
913            CooldownStatus::Cooldown => Self::Cooldown,
914            CooldownStatus::PreCooldown => Self::PreCooldown,
915            CooldownStatus::PrePreCooldown => Self::PrePreCooldown,
916        }
917    }
918}
919
920impl TryFrom<Cooldown> for super::types::Cooldown {
921    type Error = tonic::Status;
922
923    fn try_from(cd: Cooldown) -> Result<Self, Self::Error> {
924        Ok(Self {
925            status:   CooldownStatus::try_from(cd.status)
926                .map_err(|_| {
927                    tonic::Status::invalid_argument(format!(
928                        "unknown cooldown status value {}",
929                        cd.status
930                    ))
931                })?
932                .into(),
933            end_time: cd.end_time.require()?.into(),
934            amount:   cd.amount.require()?.into(),
935        })
936    }
937}
938
939impl TryFrom<AccountInfo> for super::types::AccountInfo {
940    type Error = tonic::Status;
941
942    fn try_from(value: AccountInfo) -> Result<Self, Self::Error> {
943        let AccountInfo {
944            sequence_number,
945            amount,
946            schedule,
947            creds,
948            threshold,
949            encrypted_balance,
950            encryption_key,
951            index,
952            stake,
953            address,
954            cooldowns,
955            available_balance,
956            tokens,
957        } = value;
958        let account_nonce = sequence_number.require()?.into();
959        let account_amount = amount.require()?.into();
960        let account_release_schedule: AccountReleaseSchedule = schedule.require()?.try_into()?;
961        let account_threshold = threshold.require()?.try_into()?;
962        let account_encrypted_amount = encrypted_balance.require()?.try_into()?;
963        let account_encryption_key = encryption_key.require()?.try_into()?;
964        let account_index = index.require()?.into();
965        let account_stake: Option<super::types::AccountStakingInfo> = match stake {
966            Some(stake) => Some(stake.try_into()?),
967            None => None,
968        };
969        let account_address = address.require()?.try_into()?;
970        let mut cds: Vec<super::types::Cooldown> = Vec::with_capacity(cooldowns.len());
971        for cooldown in cooldowns.into_iter() {
972            cds.push(cooldown.try_into()?)
973        }
974        let cooldowns = cds;
975
976        // The available balance is only provided as convenience and in case the
977        // calculation of it changes in the future. It should be present if the node
978        // is version 7 (or later). If the available balance is not present,
979        // we calculate it manually instead.
980        // If we up the minimum supported node version to version 7, we can remove this
981        // fallback calculation and instead require the available balance field to
982        // always be present.
983        let available_balance = available_balance.map(|ab| ab.into()).unwrap_or_else(|| {
984            let active_stake = account_stake
985                .as_ref()
986                .map(|s| s.staked_amount())
987                .unwrap_or_default();
988
989            let inactive_stake = cooldowns.iter().map(|cd| cd.amount).sum();
990
991            let staked_amount = active_stake + inactive_stake;
992
993            // The locked amount is the maximum of the amount in the release schedule and
994            // the total amount that is actively staked or in cooldown (inactive stake).
995            let locked_amount = Ord::max(account_release_schedule.total, staked_amount);
996
997            // According to the protobuf documentation:
998            // The available (unencrypted) balance of the account is the balance minus the
999            // locked amount.
1000            account_amount - locked_amount
1001        });
1002        let tokens = tokens
1003            .into_iter()
1004            .map(|token| token.try_into())
1005            .collect::<Result<_, _>>()?;
1006        Ok(Self {
1007            account_nonce,
1008            account_amount,
1009            account_release_schedule,
1010            account_credentials: creds
1011                .into_iter()
1012                .map(|(k, v)| {
1013                    let k = u8::try_from(k)
1014                        .map_err(|_| tonic::Status::internal("Unexpected credential index."))?
1015                        .into();
1016                    let v = v.try_into()?;
1017                    Ok((k, Versioned::new(VERSION_0, v)))
1018                })
1019                .collect::<Result<_, tonic::Status>>()?,
1020            account_threshold,
1021            account_encrypted_amount,
1022            account_encryption_key,
1023            account_index,
1024            account_stake,
1025            account_address,
1026            cooldowns,
1027            available_balance,
1028            tokens,
1029        })
1030    }
1031}
1032
1033impl TryFrom<BlockItemStatus> for super::types::TransactionStatus {
1034    type Error = tonic::Status;
1035
1036    fn try_from(value: BlockItemStatus) -> Result<Self, Self::Error> {
1037        match value.status.require()? {
1038            block_item_status::Status::Received(_) => Ok(super::types::TransactionStatus::Received),
1039            block_item_status::Status::Finalized(f) => {
1040                let mut summaries: BTreeMap<super::BlockHash, super::types::BlockItemSummary> =
1041                    BTreeMap::new();
1042                let o = f.outcome.require()?;
1043                let k = o.block_hash.require()?.try_into()?;
1044                let v = o.outcome.require()?.try_into()?;
1045                summaries.insert(k, v);
1046                Ok(super::types::TransactionStatus::Finalized(summaries))
1047            }
1048            block_item_status::Status::Committed(cs) => {
1049                let mut summaries: BTreeMap<super::BlockHash, super::types::BlockItemSummary> =
1050                    BTreeMap::new();
1051                for o in cs.outcomes {
1052                    let k = o.block_hash.require()?.try_into()?;
1053                    let v = o.outcome.require()?.try_into()?;
1054                    summaries.insert(k, v);
1055                }
1056                Ok(super::types::TransactionStatus::Committed(summaries))
1057            }
1058        }
1059    }
1060}
1061
1062impl TryFrom<AccountTransactionPayload> for concordium_base::transactions::EncodedPayload {
1063    type Error = tonic::Status;
1064
1065    fn try_from(value: AccountTransactionPayload) -> Result<Self, Self::Error> {
1066        use concordium_base::transactions::PayloadLike;
1067        match value.payload.require()? {
1068            account_transaction_payload::Payload::RawPayload(rp) => {
1069                Self::try_from(rp).map_err(|_| {
1070                    tonic::Status::invalid_argument("Payload size exceeds maximum allowed.")
1071                })
1072            }
1073            account_transaction_payload::Payload::DeployModule(dm) => {
1074                let module = match dm.module.require()? {
1075                    versioned_module_source::Module::V0(source) => {
1076                        concordium_base::smart_contracts::WasmModule {
1077                            version: concordium_base::smart_contracts::WasmVersion::V0,
1078                            source:  source.value.into(),
1079                        }
1080                    }
1081                    versioned_module_source::Module::V1(source) => {
1082                        concordium_base::smart_contracts::WasmModule {
1083                            version: concordium_base::smart_contracts::WasmVersion::V1,
1084                            source:  source.value.into(),
1085                        }
1086                    }
1087                };
1088                Ok(concordium_base::transactions::Payload::DeployModule { module }.encode())
1089            }
1090            account_transaction_payload::Payload::InitContract(ic) => {
1091                let payload = concordium_base::transactions::InitContractPayload {
1092                    amount:    ic.amount.require()?.into(),
1093                    mod_ref:   ic.module_ref.require()?.try_into()?,
1094                    init_name: ic.init_name.require()?.try_into()?,
1095                    param:     ic.parameter.require()?.try_into()?,
1096                };
1097                Ok(concordium_base::transactions::Payload::InitContract { payload }.encode())
1098            }
1099            account_transaction_payload::Payload::UpdateContract(uc) => {
1100                let payload = concordium_base::transactions::UpdateContractPayload {
1101                    amount:       uc.amount.require()?.into(),
1102                    address:      uc.address.require()?.into(),
1103                    receive_name: uc.receive_name.require()?.try_into()?,
1104                    message:      uc.parameter.require()?.try_into()?,
1105                };
1106                Ok(concordium_base::transactions::Payload::Update { payload }.encode())
1107            }
1108            account_transaction_payload::Payload::Transfer(t) => {
1109                let payload = concordium_base::transactions::Payload::Transfer {
1110                    to_address: t.receiver.require()?.try_into()?,
1111                    amount:     t.amount.require()?.into(),
1112                };
1113                Ok(payload.encode())
1114            }
1115            account_transaction_payload::Payload::TransferWithMemo(t) => {
1116                let payload = concordium_base::transactions::Payload::TransferWithMemo {
1117                    to_address: t.receiver.require()?.try_into()?,
1118                    amount:     t.amount.require()?.into(),
1119                    memo:       t.memo.require()?.try_into()?,
1120                };
1121                Ok(payload.encode())
1122            }
1123            account_transaction_payload::Payload::RegisterData(t) => {
1124                let payload = concordium_base::transactions::Payload::RegisterData {
1125                    data: t.try_into()?,
1126                };
1127                Ok(payload.encode())
1128            }
1129        }
1130    }
1131}
1132
1133impl TryFrom<Signature> for concordium_base::common::types::Signature {
1134    type Error = tonic::Status;
1135
1136    fn try_from(value: Signature) -> Result<Self, Self::Error> {
1137        if value.value.len() <= usize::from(u16::MAX) {
1138            Ok(Self { sig: value.value })
1139        } else {
1140            Err(tonic::Status::invalid_argument("Signature is too large."))
1141        }
1142    }
1143}
1144
1145impl TryFrom<AccountTransactionSignature> for concordium_base::common::types::TransactionSignature {
1146    type Error = tonic::Status;
1147
1148    fn try_from(value: AccountTransactionSignature) -> Result<Self, Self::Error> {
1149        let signatures = value
1150            .signatures
1151            .into_iter()
1152            .map(|(ci, m)| {
1153                let ci = u8::try_from(ci)
1154                    .map_err(|_| tonic::Status::invalid_argument("Invalid credential index."))?;
1155                let cred_sigs = m
1156                    .signatures
1157                    .into_iter()
1158                    .map(|(ki, sig)| {
1159                        let ki = u8::try_from(ki)
1160                            .map_err(|_| tonic::Status::invalid_argument("Invalid key index."))?;
1161                        let sig = sig.try_into()?;
1162                        Ok::<_, tonic::Status>((ki.into(), sig))
1163                    })
1164                    .collect::<Result<_, _>>()?;
1165                Ok::<_, tonic::Status>((ci.into(), cred_sigs))
1166            })
1167            .collect::<Result<_, _>>()?;
1168        Ok(Self { signatures })
1169    }
1170}
1171
1172impl TryFrom<AccountTransaction>
1173    for concordium_base::transactions::AccountTransaction<
1174        concordium_base::transactions::EncodedPayload,
1175    >
1176{
1177    type Error = tonic::Status;
1178
1179    fn try_from(value: AccountTransaction) -> Result<Self, Self::Error> {
1180        let payload: concordium_base::transactions::EncodedPayload =
1181            value.payload.require()?.try_into()?;
1182        let payload_size = payload.size();
1183        let header = {
1184            let header = value.header.require()?;
1185            let sender = header.sender.require()?.try_into()?;
1186            let nonce = header.sequence_number.require()?.into();
1187            let energy_amount = header.energy_amount.require()?.into();
1188            let expiry = header.expiry.require()?.into();
1189            concordium_base::transactions::TransactionHeader {
1190                sender,
1191                nonce,
1192                energy_amount,
1193                payload_size,
1194                expiry,
1195            }
1196        };
1197        Ok(Self {
1198            signature: value.signature.require()?.try_into()?,
1199            header,
1200            payload,
1201        })
1202    }
1203}
1204
1205impl TryFrom<CredentialDeployment>
1206    for crate::id::types::AccountCredentialMessage<
1207        crate::id::constants::IpPairing,
1208        crate::id::constants::ArCurve,
1209        crate::id::constants::AttributeKind,
1210    >
1211{
1212    type Error = tonic::Status;
1213
1214    fn try_from(value: CredentialDeployment) -> Result<Self, Self::Error> {
1215        let message_expiry = value.message_expiry.require()?.into();
1216        let credential_deployment::Payload::RawPayload(data) = value.payload.require()?;
1217        let credential = consume(&data)?;
1218        Ok(Self {
1219            message_expiry,
1220            credential,
1221        })
1222    }
1223}
1224
1225impl TryFrom<SignatureMap> for concordium_base::updates::UpdateInstructionSignature {
1226    type Error = tonic::Status;
1227
1228    fn try_from(value: SignatureMap) -> Result<Self, Self::Error> {
1229        let signatures = value
1230            .signatures
1231            .into_iter()
1232            .map(|(k, sig)| {
1233                let k = u16::try_from(k)
1234                    .map_err(|_| tonic::Status::invalid_argument("Update key index too large."))?;
1235                let sig = sig.try_into()?;
1236                Ok::<_, tonic::Status>((k.into(), sig))
1237            })
1238            .collect::<Result<_, _>>()?;
1239        Ok(Self { signatures })
1240    }
1241}
1242
1243impl TryFrom<UpdateInstruction> for concordium_base::updates::UpdateInstruction {
1244    type Error = tonic::Status;
1245
1246    fn try_from(value: UpdateInstruction) -> Result<Self, Self::Error> {
1247        let header = value.header.require()?;
1248        let update_instruction_payload::Payload::RawPayload(payload) =
1249            value.payload.require()?.payload.require()?;
1250        let header = concordium_base::updates::UpdateHeader {
1251            seq_number:     header.sequence_number.require()?.into(),
1252            effective_time: header.effective_time.require()?.into(),
1253            timeout:        header.timeout.require()?.into(),
1254            payload_size:   (payload.len() as u32).into(), /* as is safe since
1255                                                            * this is coming from the node, from
1256                                                            * a block */
1257        };
1258        let signatures: concordium_base::updates::UpdateInstructionSignature =
1259            value.signatures.require()?.try_into()?;
1260
1261        let payload = consume(&payload)?;
1262
1263        Ok(Self {
1264            header,
1265            payload,
1266            signatures,
1267        })
1268    }
1269}
1270
1271impl TryFrom<BlockItem>
1272    for concordium_base::transactions::BlockItem<concordium_base::transactions::EncodedPayload>
1273{
1274    type Error = tonic::Status;
1275
1276    fn try_from(value: BlockItem) -> Result<Self, Self::Error> {
1277        match value.block_item.require()? {
1278            block_item::BlockItem::AccountTransaction(at) => {
1279                Ok(Self::AccountTransaction(at.try_into()?))
1280            }
1281            block_item::BlockItem::CredentialDeployment(cd) => {
1282                Ok(Self::CredentialDeployment(Box::new(cd.try_into()?)))
1283            }
1284            block_item::BlockItem::UpdateInstruction(ui) => {
1285                Ok(Self::UpdateInstruction(ui.try_into()?))
1286            }
1287        }
1288    }
1289}
1290
1291impl TryFrom<AccountTransactionDetails> for super::types::AccountTransactionDetails {
1292    type Error = tonic::Status;
1293
1294    fn try_from(v: AccountTransactionDetails) -> Result<Self, Self::Error> {
1295        Ok(Self {
1296            cost:    v.cost.require()?.into(),
1297            sender:  v.sender.require()?.try_into()?,
1298            effects: v.effects.require()?.try_into()?,
1299        })
1300    }
1301}
1302
1303impl TryFrom<BlockItemSummary> for super::types::BlockItemSummary {
1304    type Error = tonic::Status;
1305
1306    fn try_from(value: BlockItemSummary) -> Result<Self, Self::Error> {
1307        Ok(Self {
1308            index:       value.index.require()?.into(),
1309            energy_cost: value.energy_cost.require()?.into(),
1310            hash:        value.hash.require()?.try_into()?,
1311            details:     match value.details.require()? {
1312                block_item_summary::Details::AccountTransaction(v) => {
1313                    super::types::BlockItemSummaryDetails::AccountTransaction(v.try_into()?)
1314                }
1315                block_item_summary::Details::AccountCreation(v) => {
1316                    super::types::BlockItemSummaryDetails::AccountCreation(
1317                        super::types::AccountCreationDetails {
1318                            credential_type: v.credential_type().into(),
1319                            address:         v.address.require()?.try_into()?,
1320                            reg_id:          v.reg_id.require()?.try_into()?,
1321                        },
1322                    )
1323                }
1324                block_item_summary::Details::Update(v) => {
1325                    super::types::BlockItemSummaryDetails::Update(super::types::UpdateDetails {
1326                        effective_time: v.effective_time.require()?.into(),
1327                        payload:        v.payload.require()?.try_into()?,
1328                    })
1329                }
1330                Details::TokenCreation(v) => {
1331                    super::types::BlockItemSummaryDetails::TokenCreationDetails(
1332                        super::types::TokenCreationDetails {
1333                            create_plt: v.create_plt.require()?.try_into()?,
1334                            events:     v
1335                                .events
1336                                .into_iter()
1337                                .map(TryInto::try_into)
1338                                .collect::<Result<_, tonic::Status>>()?,
1339                        },
1340                    )
1341                }
1342            },
1343        })
1344    }
1345}
1346
1347impl TryFrom<ElectionDifficulty> for super::types::ElectionDifficulty {
1348    type Error = tonic::Status;
1349
1350    fn try_from(value: ElectionDifficulty) -> Result<Self, Self::Error> {
1351        Self::new(value.value.require()?.parts_per_hundred_thousand).ok_or_else(|| {
1352            tonic::Status::internal("Election difficulty more than 1, which is not allowed.")
1353        })
1354    }
1355}
1356
1357impl TryFrom<UpdatePayload> for super::types::UpdatePayload {
1358    type Error = tonic::Status;
1359
1360    fn try_from(value: UpdatePayload) -> Result<Self, Self::Error> {
1361        Ok(match value.payload.require()? {
1362            update_payload::Payload::ProtocolUpdate(v) => Self::Protocol(v.try_into()?),
1363            update_payload::Payload::ElectionDifficultyUpdate(v) => {
1364                Self::ElectionDifficulty(v.try_into()?)
1365            }
1366            update_payload::Payload::EuroPerEnergyUpdate(v) => Self::EuroPerEnergy(v.try_into()?),
1367            update_payload::Payload::MicroCcdPerEuroUpdate(v) => {
1368                Self::MicroGTUPerEuro(v.try_into()?)
1369            }
1370            update_payload::Payload::FoundationAccountUpdate(v) => {
1371                Self::FoundationAccount(v.try_into()?)
1372            }
1373            update_payload::Payload::MintDistributionUpdate(v) => {
1374                Self::MintDistribution(v.try_into()?)
1375            }
1376            update_payload::Payload::TransactionFeeDistributionUpdate(v) => {
1377                Self::TransactionFeeDistribution(v.try_into()?)
1378            }
1379            update_payload::Payload::GasRewardsUpdate(v) => Self::GASRewards(v.try_into()?),
1380            update_payload::Payload::BakerStakeThresholdUpdate(v) => {
1381                Self::BakerStakeThreshold(v.try_into()?)
1382            }
1383            update_payload::Payload::RootUpdate(v) => {
1384                Self::Root(match v.update_type.require()? {
1385                    root_update::UpdateType::RootKeysUpdate(u) => {
1386                        super::types::RootUpdate::RootKeysUpdate(u.try_into()?)
1387                    }
1388                    root_update::UpdateType::Level1KeysUpdate(u) => {
1389                        super::types::RootUpdate::Level1KeysUpdate(u.try_into()?)
1390                    }
1391                    root_update::UpdateType::Level2KeysUpdateV0(u) => {
1392                        super::types::RootUpdate::Level2KeysUpdate(Box::new(u.try_into()?))
1393                    }
1394                    root_update::UpdateType::Level2KeysUpdateV1(u) => {
1395                        super::types::RootUpdate::Level2KeysUpdateV1(Box::new(u.try_into()?))
1396                    }
1397                })
1398            }
1399            update_payload::Payload::Level1Update(v) => {
1400                Self::Level1(match v.update_type.require()? {
1401                    level1_update::UpdateType::Level1KeysUpdate(u) => {
1402                        super::types::Level1Update::Level1KeysUpdate(u.try_into()?)
1403                    }
1404                    level1_update::UpdateType::Level2KeysUpdateV0(u) => {
1405                        super::types::Level1Update::Level2KeysUpdate(Box::new(u.try_into()?))
1406                    }
1407                    level1_update::UpdateType::Level2KeysUpdateV1(u) => {
1408                        super::types::Level1Update::Level2KeysUpdateV1(Box::new(u.try_into()?))
1409                    }
1410                })
1411            }
1412            update_payload::Payload::AddAnonymityRevokerUpdate(v) => {
1413                Self::AddAnonymityRevoker(Box::new(v.try_into()?))
1414            }
1415            update_payload::Payload::AddIdentityProviderUpdate(v) => {
1416                Self::AddIdentityProvider(Box::new(v.try_into()?))
1417            }
1418            update_payload::Payload::CooldownParametersCpv1Update(v) => {
1419                Self::CooldownParametersCPV1(v.try_into()?)
1420            }
1421            update_payload::Payload::PoolParametersCpv1Update(v) => {
1422                Self::PoolParametersCPV1(v.try_into()?)
1423            }
1424            update_payload::Payload::TimeParametersCpv1Update(v) => {
1425                Self::TimeParametersCPV1(v.try_into()?)
1426            }
1427            update_payload::Payload::MintDistributionCpv1Update(v) => {
1428                Self::MintDistributionCPV1(v.try_into()?)
1429            }
1430            update_payload::Payload::GasRewardsCpv2Update(v) => Self::GASRewardsCPV2(v.try_into()?),
1431            update_payload::Payload::TimeoutParametersUpdate(v) => {
1432                Self::TimeoutParametersCPV2(v.try_into()?)
1433            }
1434            update_payload::Payload::MinBlockTimeUpdate(v) => Self::MinBlockTimeCPV2(v.into()),
1435            update_payload::Payload::BlockEnergyLimitUpdate(v) => {
1436                Self::BlockEnergyLimitCPV2(v.into())
1437            }
1438            update_payload::Payload::FinalizationCommitteeParametersUpdate(v) => {
1439                Self::FinalizationCommitteeParametersCPV2(v.try_into()?)
1440            }
1441            update_payload::Payload::ValidatorScoreParametersUpdate(v) => {
1442                Self::ValidatorScoreParametersCPV3(v.try_into()?)
1443            }
1444            update_payload::Payload::CreatePltUpdate(create_plt) => {
1445                Self::CreatePlt(create_plt.try_into()?)
1446            }
1447        })
1448    }
1449}
1450
1451impl TryFrom<super::generated::plt::CreatePlt> for concordium_base::updates::CreatePlt {
1452    type Error = tonic::Status;
1453
1454    fn try_from(value: super::generated::plt::CreatePlt) -> Result<Self, Self::Error> {
1455        Ok(Self {
1456            token_id:                  value.token_id.require()?.try_into()?,
1457            token_module:              value.token_module.require()?.try_into()?,
1458            decimals:                  value.decimals.try_into().map_err(|_| {
1459                tonic::Status::internal("Unexpected integer size for token decimals.")
1460            })?,
1461            initialization_parameters: value.initialization_parameters.require()?.into(),
1462        })
1463    }
1464}
1465
1466impl TryFrom<CapitalBound> for super::types::CapitalBound {
1467    type Error = tonic::Status;
1468
1469    fn try_from(value: CapitalBound) -> Result<Self, Self::Error> {
1470        Ok(Self {
1471            bound: value.value.require()?.into(),
1472        })
1473    }
1474}
1475
1476impl TryFrom<InclusiveRangeAmountFraction>
1477    for super::types::InclusiveRange<super::types::AmountFraction>
1478{
1479    type Error = tonic::Status;
1480
1481    fn try_from(value: InclusiveRangeAmountFraction) -> Result<Self, Self::Error> {
1482        let min = value.min.require()?.into();
1483        let max = value.max.require()?.into();
1484        if min <= max {
1485            Ok(Self { min, max })
1486        } else {
1487            Err(tonic::Status::internal(
1488                "Lower bound must not be more than the upper bound.",
1489            ))
1490        }
1491    }
1492}
1493
1494impl From<DurationSeconds> for super::types::DurationSeconds {
1495    fn from(value: DurationSeconds) -> Self {
1496        Self {
1497            seconds: value.value,
1498        }
1499    }
1500}
1501
1502impl TryFrom<IpInfo> for crate::id::types::IpInfo<IpPairing> {
1503    type Error = tonic::Status;
1504
1505    fn try_from(value: IpInfo) -> Result<Self, Self::Error> {
1506        Ok(Self {
1507            ip_identity:       crate::id::types::IpIdentity(value.identity.require()?.value),
1508            ip_description:    value.description.require()?.into(),
1509            ip_verify_key:     value.verify_key.require()?.try_into()?,
1510            ip_cdi_verify_key: value.cdi_verify_key.require()?.try_into()?,
1511        })
1512    }
1513}
1514
1515impl TryFrom<ArInfo> for crate::id::types::ArInfo<ArCurve> {
1516    type Error = tonic::Status;
1517
1518    fn try_from(value: ArInfo) -> Result<Self, Self::Error> {
1519        Ok(Self {
1520            ar_identity:    crate::id::types::ArIdentity::try_from(value.identity.require()?.value)
1521                .map_err(tonic::Status::internal)?,
1522            ar_description: value.description.require()?.into(),
1523            ar_public_key:  value.public_key.require()?.try_into()?,
1524        })
1525    }
1526}
1527
1528impl From<Description> for crate::id::types::Description {
1529    fn from(value: Description) -> Self {
1530        Self {
1531            name:        value.name,
1532            url:         value.url,
1533            description: value.description,
1534        }
1535    }
1536}
1537
1538impl TryFrom<AuthorizationsV0> for super::types::AuthorizationsV0 {
1539    type Error = tonic::Status;
1540
1541    fn try_from(value: AuthorizationsV0) -> Result<Self, Self::Error> {
1542        Ok(Self {
1543            keys: value
1544                .keys
1545                .into_iter()
1546                .map(TryInto::try_into)
1547                .collect::<Result<_, tonic::Status>>()?,
1548            emergency: value.emergency.require()?.try_into()?,
1549            protocol: value.protocol.require()?.try_into()?,
1550            election_difficulty: value.parameter_consensus.require()?.try_into()?,
1551            euro_per_energy: value.parameter_euro_per_energy.require()?.try_into()?,
1552            micro_gtu_per_euro: value.parameter_micro_ccd_per_euro.require()?.try_into()?,
1553            foundation_account: value.parameter_foundation_account.require()?.try_into()?,
1554            mint_distribution: value.parameter_mint_distribution.require()?.try_into()?,
1555            transaction_fee_distribution: value
1556                .parameter_transaction_fee_distribution
1557                .require()?
1558                .try_into()?,
1559            param_gas_rewards: value.parameter_gas_rewards.require()?.try_into()?,
1560            pool_parameters: value.pool_parameters.require()?.try_into()?,
1561            add_anonymity_revoker: value.add_anonymity_revoker.require()?.try_into()?,
1562            add_identity_provider: value.add_identity_provider.require()?.try_into()?,
1563        })
1564    }
1565}
1566
1567impl TryFrom<AuthorizationsV1> for super::types::AuthorizationsV1 {
1568    type Error = tonic::Status;
1569
1570    fn try_from(value: AuthorizationsV1) -> Result<Self, Self::Error> {
1571        Ok(Self {
1572            v0:                  value.v0.require()?.try_into()?,
1573            cooldown_parameters: value.parameter_cooldown.require()?.try_into()?,
1574            time_parameters:     value.parameter_time.require()?.try_into()?,
1575            create_plt:          value.create_plt.map(|x| x.try_into()).transpose()?,
1576        })
1577    }
1578}
1579
1580impl TryFrom<AccessStructure> for super::types::AccessStructure {
1581    type Error = tonic::Status;
1582
1583    fn try_from(value: AccessStructure) -> Result<Self, Self::Error> {
1584        let authorized_keys = value
1585            .access_public_keys
1586            .into_iter()
1587            .map(TryInto::try_into)
1588            .collect::<Result<_, tonic::Status>>()?;
1589        let threshold = value.access_threshold.require()?.try_into()?;
1590        Ok(Self {
1591            authorized_keys,
1592            threshold,
1593        })
1594    }
1595}
1596
1597impl TryFrom<UpdateKeysIndex> for super::types::UpdateKeysIndex {
1598    type Error = tonic::Status;
1599
1600    fn try_from(value: UpdateKeysIndex) -> Result<Self, Self::Error> {
1601        Ok(Self {
1602            index: value.value.try_into().map_err(|_| {
1603                tonic::Status::internal("Invalid update keys index: could not fit into a u16.")
1604            })?,
1605        })
1606    }
1607}
1608
1609impl TryFrom<UpdateKeysThreshold> for super::types::UpdateKeysThreshold {
1610    type Error = tonic::Status;
1611
1612    fn try_from(value: UpdateKeysThreshold) -> Result<Self, Self::Error> {
1613        Self::try_from(
1614            u16::try_from(value.value)
1615                .map_err(|_| tonic::Status::internal("Threshold could not fit into a u16."))?,
1616        )
1617        .map_err(|_| tonic::Status::invalid_argument("UpdateKeysThreshold cannot be 0."))
1618    }
1619}
1620
1621impl TryFrom<MintRate> for super::types::MintRate {
1622    type Error = tonic::Status;
1623
1624    fn try_from(value: MintRate) -> Result<Self, Self::Error> {
1625        Ok(Self {
1626            mantissa: value.mantissa,
1627            exponent: value.exponent.try_into().map_err(|_| {
1628                tonic::Status::internal(
1629                    "Invalid exponent value. Could not be represented in an u8.",
1630                )
1631            })?,
1632        })
1633    }
1634}
1635
1636impl From<TransactionTime> for super::super::common::types::TransactionTime {
1637    fn from(value: TransactionTime) -> Self {
1638        Self {
1639            seconds: value.value,
1640        }
1641    }
1642}
1643
1644impl From<CredentialType> for super::types::CredentialType {
1645    fn from(value: CredentialType) -> Self {
1646        match value {
1647            CredentialType::Initial => Self::Initial,
1648            CredentialType::Normal => Self::Normal,
1649        }
1650    }
1651}
1652
1653impl TryFrom<AccountTransactionEffects> for super::types::AccountTransactionEffects {
1654    type Error = tonic::Status;
1655
1656    fn try_from(value: AccountTransactionEffects) -> Result<Self, Self::Error> {
1657        match value.effect.require()? {
1658            account_transaction_effects::Effect::None(n) => Ok(Self::None {
1659                transaction_type: {
1660                    match n.transaction_type {
1661                        None => None,
1662                        Some(tt) => Some(
1663                            super::types::TransactionType::try_from(tt)
1664                                .map_err(|e| tonic::Status::invalid_argument(e.to_string()))?,
1665                        ),
1666                    }
1667                },
1668                reject_reason:    n.reject_reason.require()?.try_into()?,
1669            }),
1670            account_transaction_effects::Effect::AccountTransfer(at) => {
1671                let amount = at.amount.require()?.into();
1672                let to = at.receiver.require()?.try_into()?;
1673                match at.memo {
1674                    None => Ok(Self::AccountTransfer { amount, to }),
1675                    Some(memo) => Ok(Self::AccountTransferWithMemo {
1676                        amount,
1677                        to,
1678                        memo: memo.try_into()?,
1679                    }),
1680                }
1681            }
1682            account_transaction_effects::Effect::ModuleDeployed(module_ref) => {
1683                Ok(Self::ModuleDeployed {
1684                    module_ref: module_ref.try_into()?,
1685                })
1686            }
1687            account_transaction_effects::Effect::ContractInitialized(cie) => {
1688                Ok(Self::ContractInitialized {
1689                    data: super::types::ContractInitializedEvent {
1690                        contract_version: cie.contract_version().into(),
1691                        origin_ref:       cie.origin_ref.require()?.try_into()?,
1692                        address:          cie.address.require()?.into(),
1693                        amount:           cie.amount.require()?.into(),
1694                        init_name:        cie.init_name.require()?.try_into()?,
1695                        events:           cie.events.into_iter().map(Into::into).collect(),
1696                        parameter:        cie.parameter.map(TryInto::try_into).transpose()?,
1697                    },
1698                })
1699            }
1700            account_transaction_effects::Effect::ContractUpdateIssued(cui) => {
1701                let effects = cui
1702                    .effects
1703                    .into_iter()
1704                    .map(TryFrom::try_from)
1705                    .collect::<Result<_, tonic::Status>>()?;
1706                Ok(Self::ContractUpdateIssued { effects })
1707            }
1708            account_transaction_effects::Effect::BakerAdded(ba) => {
1709                let baker_added_event = super::types::BakerAddedEvent {
1710                    keys_event:       ba.keys_event.require()?.try_into()?,
1711                    stake:            ba.stake.require()?.into(),
1712                    restake_earnings: ba.restake_earnings,
1713                };
1714                Ok(Self::BakerAdded {
1715                    data: Box::new(baker_added_event),
1716                })
1717            }
1718            account_transaction_effects::Effect::BakerRemoved(baker_id) => Ok(Self::BakerRemoved {
1719                baker_id: baker_id.into(),
1720            }),
1721            account_transaction_effects::Effect::BakerStakeUpdated(bsu) => {
1722                let data = match bsu.update {
1723                    None => None,
1724                    Some(d) => Some(super::types::BakerStakeUpdatedData {
1725                        baker_id:  d.baker_id.require()?.into(),
1726                        new_stake: d.new_stake.require()?.into(),
1727                        increased: d.increased,
1728                    }),
1729                };
1730                Ok(Self::BakerStakeUpdated { data })
1731            }
1732            account_transaction_effects::Effect::BakerRestakeEarningsUpdated(breu) => {
1733                Ok(Self::BakerRestakeEarningsUpdated {
1734                    baker_id:         breu.baker_id.require()?.into(),
1735                    restake_earnings: breu.restake_earnings,
1736                })
1737            }
1738            account_transaction_effects::Effect::BakerKeysUpdated(keys_event) => {
1739                Ok(Self::BakerKeysUpdated {
1740                    data: Box::new(keys_event.try_into()?),
1741                })
1742            }
1743            account_transaction_effects::Effect::EncryptedAmountTransferred(eat) => {
1744                let removed = Box::new(eat.removed.require()?.try_into()?);
1745                let added = Box::new(eat.added.require()?.try_into()?);
1746                match eat.memo {
1747                    None => Ok(Self::EncryptedAmountTransferred { removed, added }),
1748                    Some(memo) => Ok(Self::EncryptedAmountTransferredWithMemo {
1749                        removed,
1750                        added,
1751                        memo: memo.try_into()?,
1752                    }),
1753                }
1754            }
1755            account_transaction_effects::Effect::TransferredToEncrypted(esaae) => {
1756                Ok(Self::TransferredToEncrypted {
1757                    data: Box::new(super::types::EncryptedSelfAmountAddedEvent {
1758                        account:    esaae.account.require()?.try_into()?,
1759                        new_amount: esaae.new_amount.require()?.try_into()?,
1760                        amount:     esaae.amount.require()?.into(),
1761                    }),
1762                })
1763            }
1764            account_transaction_effects::Effect::TransferredToPublic(ttp) => {
1765                Ok(Self::TransferredToPublic {
1766                    removed: Box::new(ttp.removed.require()?.try_into()?),
1767                    amount:  ttp.amount.require()?.into(),
1768                })
1769            }
1770            account_transaction_effects::Effect::TransferredWithSchedule(tws) => {
1771                let to = tws.receiver.require()?.try_into()?;
1772                let amount = tws
1773                    .amount
1774                    .into_iter()
1775                    .map(TryInto::try_into)
1776                    .collect::<Result<_, tonic::Status>>()?;
1777                match tws.memo {
1778                    None => Ok(Self::TransferredWithSchedule { to, amount }),
1779                    Some(memo) => Ok(Self::TransferredWithScheduleAndMemo {
1780                        to,
1781                        amount,
1782                        memo: memo.try_into()?,
1783                    }),
1784                }
1785            }
1786            account_transaction_effects::Effect::CredentialKeysUpdated(cri) => {
1787                Ok(Self::CredentialKeysUpdated {
1788                    cred_id: cri.try_into()?,
1789                })
1790            }
1791            account_transaction_effects::Effect::CredentialsUpdated(cu) => {
1792                Ok(Self::CredentialsUpdated {
1793                    new_cred_ids:     cu
1794                        .new_cred_ids
1795                        .into_iter()
1796                        .map(TryInto::try_into)
1797                        .collect::<Result<_, tonic::Status>>()?,
1798                    removed_cred_ids: cu
1799                        .removed_cred_ids
1800                        .into_iter()
1801                        .map(TryInto::try_into)
1802                        .collect::<Result<_, tonic::Status>>()?,
1803                    new_threshold:    cu.new_threshold.require()?.try_into()?,
1804                })
1805            }
1806            account_transaction_effects::Effect::DataRegistered(rd) => Ok(Self::DataRegistered {
1807                data: rd.try_into()?,
1808            }),
1809            account_transaction_effects::Effect::BakerConfigured(bc) => Ok(Self::BakerConfigured {
1810                data: bc
1811                    .events
1812                    .into_iter()
1813                    .map(TryInto::try_into)
1814                    .collect::<Result<_, tonic::Status>>()?,
1815            }),
1816            account_transaction_effects::Effect::DelegationConfigured(dc) => {
1817                Ok(Self::DelegationConfigured {
1818                    data: dc
1819                        .events
1820                        .into_iter()
1821                        .map(TryInto::try_into)
1822                        .collect::<Result<_, tonic::Status>>()?,
1823                })
1824            }
1825            account_transaction_effects::Effect::TokenUpdateEffect(token_effect) => {
1826                Ok(Self::TokenUpdate {
1827                    events: token_effect
1828                        .events
1829                        .into_iter()
1830                        .map(TryInto::try_into)
1831                        .collect::<Result<_, tonic::Status>>()?,
1832                })
1833            }
1834        }
1835    }
1836}
1837
1838impl TryFrom<ContractTraceElement> for super::types::ContractTraceElement {
1839    type Error = tonic::Status;
1840
1841    fn try_from(e: ContractTraceElement) -> Result<Self, Self::Error> {
1842        Ok(match e.element.require()? {
1843            contract_trace_element::Element::Updated(u) => {
1844                super::types::ContractTraceElement::Updated {
1845                    data: u.try_into()?,
1846                }
1847            }
1848            contract_trace_element::Element::Transferred(t) => {
1849                super::types::ContractTraceElement::Transferred {
1850                    from:   t.sender.require()?.into(),
1851                    amount: t.amount.require()?.into(),
1852                    to:     t.receiver.require()?.try_into()?,
1853                }
1854            }
1855            contract_trace_element::Element::Interrupted(i) => {
1856                super::types::ContractTraceElement::Interrupted {
1857                    address: i.address.require()?.into(),
1858                    events:  i.events.into_iter().map(Into::into).collect(),
1859                }
1860            }
1861            contract_trace_element::Element::Resumed(r) => {
1862                super::types::ContractTraceElement::Resumed {
1863                    address: r.address.require()?.into(),
1864                    success: r.success,
1865                }
1866            }
1867            contract_trace_element::Element::Upgraded(r) => {
1868                super::types::ContractTraceElement::Upgraded {
1869                    address: r.address.require()?.into(),
1870                    from:    r.from.require()?.try_into()?,
1871                    to:      r.to.require()?.try_into()?,
1872                }
1873            }
1874        })
1875    }
1876}
1877
1878impl TryFrom<DelegationEvent> for super::types::DelegationEvent {
1879    type Error = tonic::Status;
1880
1881    fn try_from(value: DelegationEvent) -> Result<Self, Self::Error> {
1882        Ok(match value.event.require()? {
1883            delegation_event::Event::DelegationStakeIncreased(v) => {
1884                Self::DelegationStakeIncreased {
1885                    delegator_id: v.delegator_id.require()?.try_into()?,
1886                    new_stake:    v.new_stake.require()?.into(),
1887                }
1888            }
1889            delegation_event::Event::DelegationStakeDecreased(v) => {
1890                Self::DelegationStakeDecreased {
1891                    delegator_id: v.delegator_id.require()?.try_into()?,
1892                    new_stake:    v.new_stake.require()?.into(),
1893                }
1894            }
1895            delegation_event::Event::DelegationSetRestakeEarnings(v) => {
1896                Self::DelegationSetRestakeEarnings {
1897                    delegator_id:     v.delegator_id.require()?.try_into()?,
1898                    restake_earnings: v.restake_earnings,
1899                }
1900            }
1901            delegation_event::Event::DelegationSetDelegationTarget(v) => {
1902                Self::DelegationSetDelegationTarget {
1903                    delegator_id:      v.delegator_id.require()?.try_into()?,
1904                    delegation_target: v.delegation_target.require()?.try_into()?,
1905                }
1906            }
1907            delegation_event::Event::DelegationAdded(v) => Self::DelegationAdded {
1908                delegator_id: v.try_into()?,
1909            },
1910            delegation_event::Event::DelegationRemoved(v) => Self::DelegationRemoved {
1911                delegator_id: v.try_into()?,
1912            },
1913            delegation_event::Event::BakerRemoved(v) => Self::BakerRemoved {
1914                baker_id: v.baker_id.require()?.into(),
1915            },
1916        })
1917    }
1918}
1919
1920impl TryFrom<DelegatorId> for super::types::DelegatorId {
1921    type Error = tonic::Status;
1922
1923    fn try_from(value: DelegatorId) -> Result<Self, Self::Error> {
1924        Ok(Self {
1925            id: value.id.require()?.into(),
1926        })
1927    }
1928}
1929
1930impl TryFrom<BakerEvent> for super::types::BakerEvent {
1931    type Error = tonic::Status;
1932
1933    fn try_from(value: BakerEvent) -> Result<Self, Self::Error> {
1934        Ok(match value.event.require()? {
1935            baker_event::Event::BakerAdded(v) => Self::BakerAdded {
1936                data: Box::new(super::types::BakerAddedEvent {
1937                    keys_event:       v.keys_event.require()?.try_into()?,
1938                    stake:            v.stake.require()?.into(),
1939                    restake_earnings: v.restake_earnings,
1940                }),
1941            },
1942            baker_event::Event::BakerRemoved(v) => Self::BakerRemoved { baker_id: v.into() },
1943            baker_event::Event::BakerStakeIncreased(v) => Self::BakerStakeIncreased {
1944                baker_id:  v.baker_id.require()?.into(),
1945                new_stake: v.new_stake.require()?.into(),
1946            },
1947            baker_event::Event::BakerStakeDecreased(v) => Self::BakerStakeDecreased {
1948                baker_id:  v.baker_id.require()?.into(),
1949                new_stake: v.new_stake.require()?.into(),
1950            },
1951            baker_event::Event::BakerRestakeEarningsUpdated(v) => {
1952                Self::BakerRestakeEarningsUpdated {
1953                    baker_id:         v.baker_id.require()?.into(),
1954                    restake_earnings: v.restake_earnings,
1955                }
1956            }
1957            baker_event::Event::BakerKeysUpdated(v) => Self::BakerKeysUpdated {
1958                data: Box::new(v.try_into()?),
1959            },
1960            baker_event::Event::BakerSetOpenStatus(v) => {
1961                let open_status = v.open_status().into();
1962                Self::BakerSetOpenStatus {
1963                    baker_id: v.baker_id.require()?.into(),
1964                    open_status,
1965                }
1966            }
1967            baker_event::Event::BakerSetMetadataUrl(v) => Self::BakerSetMetadataURL {
1968                baker_id:     v.baker_id.require()?.into(),
1969                metadata_url: v.url.try_into().map_err(|e| {
1970                    tonic::Status::invalid_argument(format!("Invalid argument: {}", e))
1971                })?,
1972            },
1973            baker_event::Event::BakerSetTransactionFeeCommission(v) => {
1974                Self::BakerSetTransactionFeeCommission {
1975                    baker_id:                   v.baker_id.require()?.into(),
1976                    transaction_fee_commission: v.transaction_fee_commission.require()?.into(),
1977                }
1978            }
1979            baker_event::Event::BakerSetBakingRewardCommission(v) => {
1980                Self::BakerSetBakingRewardCommission {
1981                    baker_id:                 v.baker_id.require()?.into(),
1982                    baking_reward_commission: v.baking_reward_commission.require()?.into(),
1983                }
1984            }
1985            baker_event::Event::BakerSetFinalizationRewardCommission(v) => {
1986                Self::BakerSetFinalizationRewardCommission {
1987                    baker_id: v.baker_id.require()?.into(),
1988                    finalization_reward_commission: v
1989                        .finalization_reward_commission
1990                        .require()?
1991                        .into(),
1992                }
1993            }
1994            baker_event::Event::DelegationRemoved(v) => Self::DelegationRemoved {
1995                delegator_id: v.delegator_id.require()?.try_into()?,
1996            },
1997            baker_event::Event::BakerSuspended(v) => Self::BakerSuspended {
1998                baker_id: v.baker_id.require()?.into(),
1999            },
2000            baker_event::Event::BakerResumed(v) => Self::BakerResumed {
2001                baker_id: v.baker_id.require()?.into(),
2002            },
2003        })
2004    }
2005}
2006
2007impl TryFrom<RegisteredData> for super::types::RegisteredData {
2008    type Error = tonic::Status;
2009
2010    fn try_from(value: RegisteredData) -> Result<Self, Self::Error> {
2011        value
2012            .value
2013            .try_into()
2014            .map_err(|e| tonic::Status::invalid_argument(format!("{}", e)))
2015    }
2016}
2017
2018impl TryFrom<NewRelease>
2019    for (
2020        super::super::common::types::Timestamp,
2021        super::super::common::types::Amount,
2022    )
2023{
2024    type Error = tonic::Status;
2025
2026    fn try_from(value: NewRelease) -> Result<Self, Self::Error> {
2027        let timestamp = super::super::common::types::Timestamp {
2028            millis: value.timestamp.require()?.value,
2029        };
2030        Ok((timestamp, value.amount.require()?.into()))
2031    }
2032}
2033
2034impl TryFrom<EncryptedAmountRemovedEvent> for super::types::EncryptedAmountRemovedEvent {
2035    type Error = tonic::Status;
2036
2037    fn try_from(value: EncryptedAmountRemovedEvent) -> Result<Self, Self::Error> {
2038        Ok(Self {
2039            account:      value.account.require()?.try_into()?,
2040            new_amount:   value.new_amount.require()?.try_into()?,
2041            input_amount: value.input_amount.require()?.try_into()?,
2042            up_to_index:  crate::encrypted_transfers::types::EncryptedAmountAggIndex {
2043                index: value.up_to_index,
2044            },
2045        })
2046    }
2047}
2048
2049impl TryFrom<NewEncryptedAmountEvent> for super::types::NewEncryptedAmountEvent {
2050    type Error = tonic::Status;
2051
2052    fn try_from(value: NewEncryptedAmountEvent) -> Result<Self, Self::Error> {
2053        Ok(Self {
2054            receiver:         value.receiver.require()?.try_into()?,
2055            new_index:        crate::encrypted_transfers::types::EncryptedAmountIndex {
2056                index: value.new_index,
2057            },
2058            encrypted_amount: value.encrypted_amount.require()?.try_into()?,
2059        })
2060    }
2061}
2062
2063impl TryFrom<Memo> for super::types::Memo {
2064    type Error = tonic::Status;
2065
2066    fn try_from(value: Memo) -> Result<Self, Self::Error> {
2067        value
2068            .value
2069            .try_into()
2070            .map_err(|_| tonic::Status::invalid_argument("Memo is invalid because it is too big."))
2071    }
2072}
2073impl TryFrom<BakerKeysEvent> for super::types::BakerKeysEvent {
2074    type Error = tonic::Status;
2075
2076    fn try_from(value: BakerKeysEvent) -> Result<Self, Self::Error> {
2077        Ok(Self {
2078            baker_id:        value.baker_id.require()?.into(),
2079            account:         value.account.require()?.try_into()?,
2080            sign_key:        value.sign_key.require()?.try_into()?,
2081            election_key:    value.election_key.require()?.try_into()?,
2082            aggregation_key: value.aggregation_key.require()?.try_into()?,
2083        })
2084    }
2085}
2086
2087impl TryFrom<InstanceUpdatedEvent> for super::types::InstanceUpdatedEvent {
2088    type Error = tonic::Status;
2089
2090    fn try_from(value: InstanceUpdatedEvent) -> Result<Self, Self::Error> {
2091        Ok(Self {
2092            contract_version: value.contract_version().into(),
2093            address:          value.address.require()?.into(),
2094            instigator:       value.instigator.require()?.try_into()?,
2095            amount:           value.amount.require()?.into(),
2096            message:          value.parameter.require()?.try_into()?,
2097            receive_name:     value.receive_name.require()?.try_into()?,
2098            events:           value.events.into_iter().map(Into::into).collect(),
2099        })
2100    }
2101}
2102
2103impl From<ContractVersion> for super::types::smart_contracts::WasmVersion {
2104    fn from(value: ContractVersion) -> Self {
2105        match value {
2106            ContractVersion::V0 => Self::V0,
2107            ContractVersion::V1 => Self::V1,
2108        }
2109    }
2110}
2111
2112impl From<ContractEvent> for super::types::smart_contracts::ContractEvent {
2113    fn from(value: ContractEvent) -> Self { value.value.into() }
2114}
2115
2116impl TryFrom<RejectReason> for super::types::RejectReason {
2117    type Error = tonic::Status;
2118
2119    fn try_from(value: RejectReason) -> Result<Self, Self::Error> {
2120        Ok(match value.reason.require()? {
2121            reject_reason::Reason::ModuleNotWf(_) => Self::ModuleNotWF,
2122            reject_reason::Reason::ModuleHashAlreadyExists(v) => Self::ModuleHashAlreadyExists {
2123                contents: v.try_into()?,
2124            },
2125            reject_reason::Reason::InvalidAccountReference(v) => Self::InvalidAccountReference {
2126                contents: v.try_into()?,
2127            },
2128            reject_reason::Reason::InvalidInitMethod(v) => Self::InvalidInitMethod {
2129                contents: (
2130                    v.module_ref.require()?.try_into()?,
2131                    v.init_name.require()?.try_into()?,
2132                ),
2133            },
2134            reject_reason::Reason::InvalidReceiveMethod(v) => Self::InvalidReceiveMethod {
2135                contents: (
2136                    v.module_ref.require()?.try_into()?,
2137                    v.receive_name.require()?.try_into()?,
2138                ),
2139            },
2140            reject_reason::Reason::InvalidModuleReference(v) => Self::InvalidModuleReference {
2141                contents: v.try_into()?,
2142            },
2143            reject_reason::Reason::InvalidContractAddress(v) => {
2144                Self::InvalidContractAddress { contents: v.into() }
2145            }
2146            reject_reason::Reason::RuntimeFailure(_) => Self::RuntimeFailure,
2147            reject_reason::Reason::AmountTooLarge(v) => Self::AmountTooLarge {
2148                contents: (v.address.require()?.try_into()?, v.amount.require()?.into()),
2149            },
2150            reject_reason::Reason::SerializationFailure(_) => Self::SerializationFailure,
2151            reject_reason::Reason::OutOfEnergy(_) => Self::OutOfEnergy,
2152            reject_reason::Reason::RejectedInit(v) => Self::RejectedInit {
2153                reject_reason: v.reject_reason,
2154            },
2155            reject_reason::Reason::RejectedReceive(v) => Self::RejectedReceive {
2156                reject_reason:    v.reject_reason,
2157                contract_address: v.contract_address.require()?.into(),
2158                receive_name:     v.receive_name.require()?.try_into()?,
2159                parameter:        v.parameter.require()?.try_into()?,
2160            },
2161            reject_reason::Reason::InvalidProof(_) => Self::InvalidProof,
2162            reject_reason::Reason::AlreadyABaker(v) => Self::AlreadyABaker { contents: v.into() },
2163            reject_reason::Reason::NotABaker(v) => Self::NotABaker {
2164                contents: v.try_into()?,
2165            },
2166            reject_reason::Reason::InsufficientBalanceForBakerStake(_) => {
2167                Self::InsufficientBalanceForBakerStake
2168            }
2169            reject_reason::Reason::StakeUnderMinimumThresholdForBaking(_) => {
2170                Self::StakeUnderMinimumThresholdForBaking
2171            }
2172            reject_reason::Reason::BakerInCooldown(_) => Self::BakerInCooldown,
2173            reject_reason::Reason::DuplicateAggregationKey(v) => Self::DuplicateAggregationKey {
2174                contents: Box::new(v.try_into()?),
2175            },
2176            reject_reason::Reason::NonExistentCredentialId(_) => Self::NonExistentCredentialID,
2177            reject_reason::Reason::KeyIndexAlreadyInUse(_) => Self::KeyIndexAlreadyInUse,
2178            reject_reason::Reason::InvalidAccountThreshold(_) => Self::InvalidAccountThreshold,
2179            reject_reason::Reason::InvalidCredentialKeySignThreshold(_) => {
2180                Self::InvalidCredentialKeySignThreshold
2181            }
2182            reject_reason::Reason::InvalidEncryptedAmountTransferProof(_) => {
2183                Self::InvalidEncryptedAmountTransferProof
2184            }
2185            reject_reason::Reason::InvalidTransferToPublicProof(_) => {
2186                Self::InvalidTransferToPublicProof
2187            }
2188            reject_reason::Reason::EncryptedAmountSelfTransfer(v) => {
2189                Self::EncryptedAmountSelfTransfer {
2190                    contents: v.try_into()?,
2191                }
2192            }
2193            reject_reason::Reason::InvalidIndexOnEncryptedTransfer(_) => {
2194                Self::InvalidIndexOnEncryptedTransfer
2195            }
2196            reject_reason::Reason::ZeroScheduledAmount(_) => Self::ZeroScheduledAmount,
2197            reject_reason::Reason::NonIncreasingSchedule(_) => Self::NonIncreasingSchedule,
2198            reject_reason::Reason::FirstScheduledReleaseExpired(_) => {
2199                Self::FirstScheduledReleaseExpired
2200            }
2201            reject_reason::Reason::ScheduledSelfTransfer(v) => Self::ScheduledSelfTransfer {
2202                contents: v.try_into()?,
2203            },
2204            reject_reason::Reason::InvalidCredentials(_) => Self::InvalidCredentials,
2205            reject_reason::Reason::DuplicateCredIds(v) => Self::DuplicateCredIDs {
2206                contents: v
2207                    .ids
2208                    .into_iter()
2209                    .map(TryFrom::try_from)
2210                    .collect::<Result<_, tonic::Status>>()?,
2211            },
2212            reject_reason::Reason::NonExistentCredIds(v) => Self::NonExistentCredIDs {
2213                contents: v
2214                    .ids
2215                    .into_iter()
2216                    .map(TryFrom::try_from)
2217                    .collect::<Result<_, tonic::Status>>()?,
2218            },
2219            reject_reason::Reason::RemoveFirstCredential(_) => Self::RemoveFirstCredential,
2220            reject_reason::Reason::CredentialHolderDidNotSign(_) => {
2221                Self::CredentialHolderDidNotSign
2222            }
2223            reject_reason::Reason::NotAllowedMultipleCredentials(_) => {
2224                Self::NotAllowedMultipleCredentials
2225            }
2226            reject_reason::Reason::NotAllowedToReceiveEncrypted(_) => {
2227                Self::NotAllowedToReceiveEncrypted
2228            }
2229            reject_reason::Reason::NotAllowedToHandleEncrypted(_) => {
2230                Self::NotAllowedToHandleEncrypted
2231            }
2232            reject_reason::Reason::MissingBakerAddParameters(_) => Self::MissingBakerAddParameters,
2233            reject_reason::Reason::FinalizationRewardCommissionNotInRange(_) => {
2234                Self::FinalizationRewardCommissionNotInRange
2235            }
2236            reject_reason::Reason::BakingRewardCommissionNotInRange(_) => {
2237                Self::BakingRewardCommissionNotInRange
2238            }
2239            reject_reason::Reason::TransactionFeeCommissionNotInRange(_) => {
2240                Self::TransactionFeeCommissionNotInRange
2241            }
2242            reject_reason::Reason::AlreadyADelegator(_) => Self::AlreadyADelegator,
2243            reject_reason::Reason::InsufficientBalanceForDelegationStake(_) => {
2244                Self::InsufficientBalanceForDelegationStake
2245            }
2246            reject_reason::Reason::MissingDelegationAddParameters(_) => {
2247                Self::MissingDelegationAddParameters
2248            }
2249            reject_reason::Reason::InsufficientDelegationStake(_) => {
2250                Self::InsufficientDelegationStake
2251            }
2252            reject_reason::Reason::DelegatorInCooldown(_) => Self::DelegatorInCooldown,
2253            reject_reason::Reason::NotADelegator(v) => Self::NotADelegator {
2254                address: v.try_into()?,
2255            },
2256            reject_reason::Reason::DelegationTargetNotABaker(v) => {
2257                Self::DelegationTargetNotABaker { target: v.into() }
2258            }
2259            reject_reason::Reason::StakeOverMaximumThresholdForPool(_) => {
2260                Self::StakeOverMaximumThresholdForPool
2261            }
2262            reject_reason::Reason::PoolWouldBecomeOverDelegated(_) => {
2263                Self::PoolWouldBecomeOverDelegated
2264            }
2265            reject_reason::Reason::PoolClosed(_) => Self::PoolClosed,
2266            reject_reason::Reason::NonExistentTokenId(token_id) => Self::NonExistentTokenId {
2267                token_id: token_id.try_into()?,
2268            },
2269            reject_reason::Reason::TokenUpdateTransactionFailed(token_module_reject_reason) => {
2270                Self::TokenUpdateTransactionFailed {
2271                    reject_reason: token_module_reject_reason.try_into()?,
2272                }
2273            }
2274        })
2275    }
2276}
2277
2278impl TryFrom<NextAccountSequenceNumber> for super::types::queries::AccountNonceResponse {
2279    type Error = tonic::Status;
2280
2281    fn try_from(value: NextAccountSequenceNumber) -> Result<Self, Self::Error> {
2282        Ok(Self {
2283            nonce:     value.sequence_number.require()?.into(),
2284            all_final: value.all_final,
2285        })
2286    }
2287}
2288
2289impl From<block_item_summary::TransactionIndex> for super::types::TransactionIndex {
2290    fn from(value: block_item_summary::TransactionIndex) -> Self { Self { index: value.value } }
2291}
2292
2293impl From<Energy> for super::types::Energy {
2294    fn from(value: Energy) -> Self {
2295        Self {
2296            energy: value.value,
2297        }
2298    }
2299}
2300
2301impl TryFrom<ConsensusInfo> for super::types::queries::ConsensusInfo {
2302    type Error = tonic::Status;
2303
2304    fn try_from(value: ConsensusInfo) -> Result<Self, Self::Error> {
2305        let protocol_version = ProtocolVersion::try_from(value.protocol_version)
2306            .map_err(|_| tonic::Status::internal("Unknown protocol version"))?
2307            .into();
2308        Ok(Self {
2309            last_finalized_block_height: value.last_finalized_block_height.require()?.into(),
2310            block_arrive_latency_e_m_s_d: value.block_arrive_latency_emsd,
2311            block_receive_latency_e_m_s_d: value.block_receive_latency_emsd,
2312            last_finalized_block: value.last_finalized_block.require()?.try_into()?,
2313            block_receive_period_e_m_s_d: value.block_receive_period_emsd,
2314            block_arrive_period_e_m_s_d: value.block_arrive_period_emsd,
2315            blocks_received_count: value.blocks_received_count.into(),
2316            transactions_per_block_e_m_s_d: value.transactions_per_block_emsd,
2317            finalization_period_e_m_a: value.finalization_period_ema,
2318            best_block_height: value.best_block_height.require()?.into(),
2319            last_finalized_time: value
2320                .last_finalized_time
2321                .map(|v| v.try_into())
2322                .transpose()?,
2323            finalization_count: value.finalization_count.into(),
2324            epoch_duration: value.epoch_duration.require()?.try_into()?,
2325            blocks_verified_count: value.blocks_verified_count.into(),
2326            slot_duration: value.slot_duration.map(Into::into),
2327            genesis_time: value.genesis_time.require()?.try_into()?,
2328            finalization_period_e_m_s_d: value.finalization_period_emsd,
2329            transactions_per_block_e_m_a: value.transactions_per_block_ema,
2330            block_arrive_latency_e_m_a: value.block_arrive_latency_ema,
2331            block_receive_latency_e_m_a: value.block_receive_latency_ema,
2332            block_arrive_period_e_m_a: value.block_arrive_period_ema,
2333            block_receive_period_e_m_a: value.block_receive_period_ema,
2334            block_last_arrived_time: value
2335                .block_last_arrived_time
2336                .map(|v| v.try_into())
2337                .transpose()?,
2338            best_block: value.best_block.require()?.try_into()?,
2339            genesis_block: value.genesis_block.require()?.try_into()?,
2340            block_last_received_time: value
2341                .block_last_received_time
2342                .map(|v| v.try_into())
2343                .transpose()?,
2344            protocol_version,
2345            genesis_index: value.genesis_index.require()?.into(),
2346            current_era_genesis_block: value.current_era_genesis_block.require()?.try_into()?,
2347            current_era_genesis_time: value.current_era_genesis_time.require()?.try_into()?,
2348            concordium_bft_status: if protocol_version <= super::types::ProtocolVersion::P5 {
2349                None
2350            } else {
2351                Some(ConcordiumBFTDetails {
2352                    current_timeout_duration: value
2353                        .current_timeout_duration
2354                        .require()?
2355                        .try_into()?,
2356                    current_round:            value.current_round.require()?.into(),
2357                    current_epoch:            value.current_epoch.require()?.into(),
2358                    trigger_block_time:       value.trigger_block_time.require()?.try_into()?,
2359                })
2360            },
2361        })
2362    }
2363}
2364
2365impl TryFrom<InvokeInstanceResponse> for super::types::smart_contracts::InvokeContractResult {
2366    type Error = tonic::Status;
2367
2368    fn try_from(response: InvokeInstanceResponse) -> Result<Self, Self::Error> {
2369        use super::types::smart_contracts::{InvokeContractResult, ReturnValue};
2370        let result = match response.result.require()? {
2371            invoke_instance_response::Result::Failure(value) => InvokeContractResult::Failure {
2372                return_value: value.return_value.map(|b| ReturnValue { value: b }),
2373                reason:       value.reason.require()?.try_into()?,
2374                used_energy:  value.used_energy.require()?.into(),
2375            },
2376            invoke_instance_response::Result::Success(value) => InvokeContractResult::Success {
2377                return_value: value.return_value.map(|b| ReturnValue { value: b }),
2378                events:       value
2379                    .effects
2380                    .into_iter()
2381                    .map(TryFrom::try_from)
2382                    .collect::<Result<_, tonic::Status>>()?,
2383                used_energy:  value.used_energy.require()?.into(),
2384            },
2385        };
2386        Ok(result)
2387    }
2388}
2389
2390impl TryFrom<CryptographicParameters> for super::types::CryptographicParameters {
2391    type Error = tonic::Status;
2392
2393    fn try_from(value: CryptographicParameters) -> Result<Self, Self::Error> {
2394        Ok(Self {
2395            genesis_string:          value.genesis_string,
2396            on_chain_commitment_key: concordium_base::common::from_bytes(
2397                &mut std::io::Cursor::new(&value.on_chain_commitment_key),
2398            )
2399            .map_err(|_| tonic::Status::internal("Invalid on_chain_commitment_key received"))?,
2400
2401            bulletproof_generators: concordium_base::common::from_bytes(&mut std::io::Cursor::new(
2402                &value.bulletproof_generators,
2403            ))
2404            .map_err(|_| tonic::Status::internal("Invalid bulletproof_generators received"))?,
2405        })
2406    }
2407}
2408
2409impl TryFrom<CredentialsPerBlockLimit> for super::types::CredentialsPerBlockLimit {
2410    type Error = tonic::Status;
2411
2412    fn try_from(value: CredentialsPerBlockLimit) -> Result<Self, Self::Error> {
2413        Ok(Self {
2414            limit: value.value.try_into().map_err(|_| {
2415                tonic::Status::internal("Unexpectedly large account creation limit")
2416            })?,
2417        })
2418    }
2419}
2420
2421impl TryFrom<ChainParametersV0> for super::ChainParametersV0 {
2422    type Error = tonic::Status;
2423
2424    fn try_from(value: ChainParametersV0) -> Result<Self, Self::Error> {
2425        Ok(Self {
2426            election_difficulty: value.election_difficulty.require()?.try_into()?,
2427            euro_per_energy: value.euro_per_energy.require()?.try_into()?,
2428            micro_ccd_per_euro: value.micro_ccd_per_euro.require()?.try_into()?,
2429            baker_cooldown_epochs: value.baker_cooldown_epochs.require()?.into(),
2430            account_creation_limit: value.account_creation_limit.require()?.try_into()?,
2431            mint_distribution: value.mint_distribution.require()?.try_into()?,
2432            transaction_fee_distribution: value
2433                .transaction_fee_distribution
2434                .require()?
2435                .try_into()?,
2436            gas_rewards: value.gas_rewards.require()?.try_into()?,
2437            foundation_account: value.foundation_account.require()?.try_into()?,
2438            minimum_threshold_for_baking: value.minimum_threshold_for_baking.require()?.into(),
2439            keys: UpdateKeysCollectionSkeleton {
2440                root_keys:    value.root_keys.require()?.try_into()?,
2441                level_1_keys: value.level1_keys.require()?.try_into()?,
2442                level_2_keys: value.level2_keys.require()?.try_into()?,
2443            },
2444        })
2445    }
2446}
2447
2448impl TryFrom<ChainParametersV1> for super::ChainParametersV1 {
2449    type Error = tonic::Status;
2450
2451    fn try_from(value: ChainParametersV1) -> Result<Self, Self::Error> {
2452        Ok(Self {
2453            election_difficulty: value.election_difficulty.require()?.try_into()?,
2454            euro_per_energy: value.euro_per_energy.require()?.try_into()?,
2455            micro_ccd_per_euro: value.micro_ccd_per_euro.require()?.try_into()?,
2456            pool_parameters: value.pool_parameters.require()?.try_into()?,
2457            account_creation_limit: value.account_creation_limit.require()?.try_into()?,
2458            mint_distribution: value.mint_distribution.require()?.try_into()?,
2459            transaction_fee_distribution: value
2460                .transaction_fee_distribution
2461                .require()?
2462                .try_into()?,
2463            gas_rewards: value.gas_rewards.require()?.try_into()?,
2464            foundation_account: value.foundation_account.require()?.try_into()?,
2465            time_parameters: value.time_parameters.require()?.try_into()?,
2466            cooldown_parameters: value.cooldown_parameters.require()?.try_into()?,
2467            keys: UpdateKeysCollectionSkeleton {
2468                root_keys:    value.root_keys.require()?.try_into()?,
2469                level_1_keys: value.level1_keys.require()?.try_into()?,
2470                level_2_keys: value.level2_keys.require()?.try_into()?,
2471            },
2472        })
2473    }
2474}
2475
2476impl TryFrom<ChainParametersV2> for super::ChainParametersV2 {
2477    type Error = tonic::Status;
2478
2479    fn try_from(value: ChainParametersV2) -> Result<Self, Self::Error> {
2480        let consensus_parameters = value.consensus_parameters.require()?;
2481
2482        Ok(Self {
2483            timeout_parameters: consensus_parameters
2484                .timeout_parameters
2485                .require()?
2486                .try_into()?,
2487            min_block_time: consensus_parameters.min_block_time.require()?.into(),
2488            block_energy_limit: consensus_parameters.block_energy_limit.require()?.into(),
2489            euro_per_energy: value.euro_per_energy.require()?.try_into()?,
2490            micro_ccd_per_euro: value.micro_ccd_per_euro.require()?.try_into()?,
2491            pool_parameters: value.pool_parameters.require()?.try_into()?,
2492            account_creation_limit: value.account_creation_limit.require()?.try_into()?,
2493            mint_distribution: value.mint_distribution.require()?.try_into()?,
2494            transaction_fee_distribution: value
2495                .transaction_fee_distribution
2496                .require()?
2497                .try_into()?,
2498            gas_rewards: value.gas_rewards.require()?.try_into()?,
2499            foundation_account: value.foundation_account.require()?.try_into()?,
2500            time_parameters: value.time_parameters.require()?.try_into()?,
2501            cooldown_parameters: value.cooldown_parameters.require()?.try_into()?,
2502            finalization_committee_parameters: value
2503                .finalization_committee_parameters
2504                .require()?
2505                .try_into()?,
2506            keys: UpdateKeysCollectionSkeleton {
2507                root_keys:    value.root_keys.require()?.try_into()?,
2508                level_1_keys: value.level1_keys.require()?.try_into()?,
2509                level_2_keys: value.level2_keys.require()?.try_into()?,
2510            },
2511        })
2512    }
2513}
2514
2515impl TryFrom<ChainParametersV3> for super::ChainParametersV3 {
2516    type Error = tonic::Status;
2517
2518    fn try_from(value: ChainParametersV3) -> Result<Self, Self::Error> {
2519        let consensus_parameters = value.consensus_parameters.require()?;
2520
2521        Ok(Self {
2522            timeout_parameters: consensus_parameters
2523                .timeout_parameters
2524                .require()?
2525                .try_into()?,
2526            min_block_time: consensus_parameters.min_block_time.require()?.into(),
2527            block_energy_limit: consensus_parameters.block_energy_limit.require()?.into(),
2528            euro_per_energy: value.euro_per_energy.require()?.try_into()?,
2529            micro_ccd_per_euro: value.micro_ccd_per_euro.require()?.try_into()?,
2530            pool_parameters: value.pool_parameters.require()?.try_into()?,
2531            account_creation_limit: value.account_creation_limit.require()?.try_into()?,
2532            mint_distribution: value.mint_distribution.require()?.try_into()?,
2533            transaction_fee_distribution: value
2534                .transaction_fee_distribution
2535                .require()?
2536                .try_into()?,
2537            gas_rewards: value.gas_rewards.require()?.try_into()?,
2538            foundation_account: value.foundation_account.require()?.try_into()?,
2539            time_parameters: value.time_parameters.require()?.try_into()?,
2540            cooldown_parameters: value.cooldown_parameters.require()?.try_into()?,
2541            finalization_committee_parameters: value
2542                .finalization_committee_parameters
2543                .require()?
2544                .try_into()?,
2545            validator_score_parameters: value.validator_score_parameters.require()?.try_into()?,
2546            keys: UpdateKeysCollectionSkeleton {
2547                root_keys:    value.root_keys.require()?.try_into()?,
2548                level_1_keys: value.level1_keys.require()?.try_into()?,
2549                level_2_keys: value.level2_keys.require()?.try_into()?,
2550            },
2551        })
2552    }
2553}
2554
2555impl TryFrom<ChainParameters> for super::ChainParameters {
2556    type Error = tonic::Status;
2557
2558    fn try_from(value: ChainParameters) -> Result<Self, Self::Error> {
2559        match value.parameters.require()? {
2560            chain_parameters::Parameters::V0(v0) => Ok(Self::V0(v0.try_into()?)),
2561            chain_parameters::Parameters::V1(v1) => Ok(Self::V1(v1.try_into()?)),
2562            chain_parameters::Parameters::V2(v2) => Ok(Self::V2(v2.try_into()?)),
2563            chain_parameters::Parameters::V3(v3) => Ok(Self::V3(v3.try_into()?)),
2564        }
2565    }
2566}
2567
2568impl TryFrom<FinalizationSummaryParty> for super::types::FinalizationSummaryParty {
2569    type Error = tonic::Status;
2570
2571    fn try_from(value: FinalizationSummaryParty) -> Result<Self, Self::Error> {
2572        Ok(Self {
2573            baker_id: value.baker.require()?.into(),
2574            weight:   value.weight,
2575            signed:   value.signed,
2576        })
2577    }
2578}
2579
2580impl From<FinalizationIndex> for super::types::FinalizationIndex {
2581    fn from(value: FinalizationIndex) -> Self { value.value.into() }
2582}
2583
2584impl TryFrom<BlockFinalizationSummary> for Option<super::types::FinalizationSummary> {
2585    type Error = tonic::Status;
2586
2587    fn try_from(value: BlockFinalizationSummary) -> Result<Self, Self::Error> {
2588        match value.summary.require()? {
2589            block_finalization_summary::Summary::None(_) => Ok(None),
2590            block_finalization_summary::Summary::Record(r) => {
2591                Ok(Some(super::types::FinalizationSummary {
2592                    block_pointer: r.block.require()?.try_into()?,
2593                    index:         r.index.require()?.into(),
2594                    delay:         r.delay.require()?.into(),
2595                    finalizers:    r
2596                        .finalizers
2597                        .into_iter()
2598                        .map(super::types::FinalizationSummaryParty::try_from)
2599                        .collect::<Result<_, tonic::Status>>()?,
2600                }))
2601            }
2602        }
2603    }
2604}
2605
2606impl TryFrom<BlockInfo> for super::types::queries::BlockInfo {
2607    type Error = tonic::Status;
2608
2609    fn try_from(value: BlockInfo) -> Result<Self, Self::Error> {
2610        let protocol_version = ProtocolVersion::try_from(value.protocol_version)
2611            .map_err(|_| {
2612                tonic::Status::internal(format!(
2613                    "Unknown protocol version: {}",
2614                    value.protocol_version
2615                ))
2616            })?
2617            .into();
2618        Ok(Self {
2619            transactions_size: value.transactions_size.into(),
2620            block_parent: value.parent_block.require()?.try_into()?,
2621            block_hash: value.hash.require()?.try_into()?,
2622            finalized: value.finalized,
2623            block_state_hash: value.state_hash.require()?.try_into()?,
2624            block_arrive_time: value.arrive_time.require()?.try_into()?,
2625            block_receive_time: value.receive_time.require()?.try_into()?,
2626            transaction_count: value.transaction_count.into(),
2627            transaction_energy_cost: value.transactions_energy_cost.require()?.into(),
2628            block_slot: if protocol_version <= super::types::ProtocolVersion::P5 {
2629                Some(value.slot_number.require()?.into())
2630            } else {
2631                None
2632            },
2633            block_last_finalized: value.last_finalized_block.require()?.try_into()?,
2634            block_slot_time: value.slot_time.require()?.try_into()?,
2635            block_height: value.height.require()?.into(),
2636            era_block_height: value.era_block_height.require()?.into(),
2637            genesis_index: value.genesis_index.require()?.into(),
2638            block_baker: value.baker.map(|b| b.into()),
2639            protocol_version,
2640            round: if protocol_version >= super::types::ProtocolVersion::P6 {
2641                Some(value.round.require()?.into())
2642            } else {
2643                None
2644            },
2645            epoch: if protocol_version >= super::types::ProtocolVersion::P6 {
2646                Some(value.epoch.require()?.into())
2647            } else {
2648                None
2649            },
2650        })
2651    }
2652}
2653
2654impl TryFrom<PoolInfoResponse> for super::types::BakerPoolStatus {
2655    type Error = tonic::Status;
2656
2657    fn try_from(value: PoolInfoResponse) -> Result<Self, Self::Error> {
2658        // The active baker pool status is present iff the pool info is present in the
2659        // response.
2660        let active_baker_pool_status = match value.pool_info {
2661            None => None,
2662            Some(pi) => Some(ActiveBakerPoolStatus {
2663                baker_equity_capital:       value.equity_capital.require()?.into(),
2664                delegated_capital:          value.delegated_capital.require()?.into(),
2665                delegated_capital_cap:      value.delegated_capital_cap.require()?.into(),
2666                pool_info:                  pi.try_into()?,
2667                baker_stake_pending_change: value.equity_pending_change.try_into()?,
2668            }),
2669        };
2670
2671        Ok(Self {
2672            baker_id: value.baker.require()?.into(),
2673            baker_address: value.address.require()?.try_into()?,
2674            active_baker_pool_status,
2675            current_payday_status: if let Some(v) = value.current_payday_info {
2676                Some(v.try_into()?)
2677            } else {
2678                None
2679            },
2680            all_pool_total_capital: value.all_pool_total_capital.require()?.into(),
2681        })
2682    }
2683}
2684
2685impl TryFrom<Option<PoolPendingChange>> for super::types::PoolPendingChange {
2686    type Error = tonic::Status;
2687
2688    fn try_from(value: Option<PoolPendingChange>) -> Result<Self, Self::Error> {
2689        if let Some(value) = value {
2690            match value.change.require()? {
2691                pool_pending_change::Change::Reduce(rs) => Ok(Self::ReduceBakerCapital {
2692                    baker_equity_capital: rs.reduced_equity_capital.require()?.into(),
2693                    effective_time:       rs.effective_time.require()?.try_into()?,
2694                }),
2695                pool_pending_change::Change::Remove(rs) => Ok(Self::RemovePool {
2696                    effective_time: rs.effective_time.require()?.try_into()?,
2697                }),
2698            }
2699        } else {
2700            Ok(Self::NoChange)
2701        }
2702    }
2703}
2704
2705impl TryFrom<PoolCurrentPaydayInfo> for super::types::CurrentPaydayBakerPoolStatus {
2706    type Error = tonic::Status;
2707
2708    fn try_from(value: PoolCurrentPaydayInfo) -> Result<Self, Self::Error> {
2709        Ok(Self {
2710            blocks_baked:            value.blocks_baked,
2711            finalization_live:       value.finalization_live,
2712            transaction_fees_earned: value.transaction_fees_earned.require()?.into(),
2713            effective_stake:         value.effective_stake.require()?.into(),
2714            lottery_power:           value.lottery_power,
2715            baker_equity_capital:    value.baker_equity_capital.require()?.into(),
2716            delegated_capital:       value.delegated_capital.require()?.into(),
2717            commission_rates:        value.commission_rates.require()?.try_into()?,
2718        })
2719    }
2720}
2721
2722impl TryFrom<PassiveDelegationInfo> for super::types::PassiveDelegationStatus {
2723    type Error = tonic::Status;
2724
2725    fn try_from(value: PassiveDelegationInfo) -> Result<Self, Self::Error> {
2726        Ok(Self {
2727            delegated_capital: value.delegated_capital.require()?.into(),
2728            commission_rates: value.commission_rates.require()?.try_into()?,
2729            current_payday_transaction_fees_earned: value
2730                .current_payday_transaction_fees_earned
2731                .require()?
2732                .into(),
2733            current_payday_delegated_capital: value
2734                .current_payday_delegated_capital
2735                .require()?
2736                .into(),
2737            all_pool_total_capital: value.all_pool_total_capital.require()?.into(),
2738        })
2739    }
2740}
2741
2742impl From<&super::endpoints::BlocksAtHeightInput> for BlocksAtHeightRequest {
2743    fn from(&input: &super::endpoints::BlocksAtHeightInput) -> Self {
2744        let blocks_at_height = match input {
2745            super::endpoints::BlocksAtHeightInput::Absolute { height } => {
2746                blocks_at_height_request::BlocksAtHeight::Absolute(
2747                    blocks_at_height_request::Absolute {
2748                        height: Some(height.into()),
2749                    },
2750                )
2751            }
2752
2753            super::endpoints::BlocksAtHeightInput::Relative {
2754                height,
2755                genesis_index,
2756                restrict,
2757            } => blocks_at_height_request::BlocksAtHeight::Relative(
2758                blocks_at_height_request::Relative {
2759                    height: Some(height.into()),
2760                    genesis_index: Some(genesis_index.into()),
2761                    restrict,
2762                },
2763            ),
2764        };
2765        BlocksAtHeightRequest {
2766            blocks_at_height: Some(blocks_at_height),
2767        }
2768    }
2769}
2770
2771impl TryFrom<TokenomicsInfo> for super::types::RewardsOverview {
2772    type Error = tonic::Status;
2773
2774    fn try_from(value: TokenomicsInfo) -> Result<Self, Self::Error> {
2775        match value.tokenomics.require()? {
2776            tokenomics_info::Tokenomics::V0(value) => Ok(Self::V0 {
2777                data: super::types::CommonRewardData {
2778                    protocol_version:            ProtocolVersion::try_from(value.protocol_version)
2779                        .map_err(|_| {
2780                            tonic::Status::internal(format!(
2781                                "Unknown protocol version: {}",
2782                                value.protocol_version
2783                            ))
2784                        })?
2785                        .into(),
2786                    total_amount:                value.total_amount.require()?.into(),
2787                    total_encrypted_amount:      value.total_encrypted_amount.require()?.into(),
2788                    baking_reward_account:       value.baking_reward_account.require()?.into(),
2789                    finalization_reward_account: value
2790                        .finalization_reward_account
2791                        .require()?
2792                        .into(),
2793                    gas_account:                 value.gas_account.require()?.into(),
2794                },
2795            }),
2796            tokenomics_info::Tokenomics::V1(value) => Ok(Self::V1 {
2797                common: super::types::CommonRewardData {
2798                    protocol_version:            ProtocolVersion::try_from(value.protocol_version)
2799                        .map_err(|_| {
2800                            tonic::Status::internal(format!(
2801                                "Unknown protocol version: {}",
2802                                value.protocol_version
2803                            ))
2804                        })?
2805                        .into(),
2806                    total_amount:                value.total_amount.require()?.into(),
2807                    total_encrypted_amount:      value.total_encrypted_amount.require()?.into(),
2808                    baking_reward_account:       value.baking_reward_account.require()?.into(),
2809                    finalization_reward_account: value
2810                        .finalization_reward_account
2811                        .require()?
2812                        .into(),
2813                    gas_account:                 value.gas_account.require()?.into(),
2814                },
2815                foundation_transaction_rewards: value
2816                    .foundation_transaction_rewards
2817                    .require()?
2818                    .into(),
2819                next_payday_time: value.next_payday_time.require()?.try_into()?,
2820                next_payday_mint_rate: value.next_payday_mint_rate.require()?.try_into()?,
2821                total_staked_capital: value.total_staked_capital.require()?.into(),
2822            }),
2823        }
2824    }
2825}
2826
2827impl TryFrom<Branch> for super::types::queries::Branch {
2828    type Error = tonic::Status;
2829
2830    fn try_from(value: Branch) -> Result<Self, Self::Error> {
2831        // Tracking the branches which to visit next.
2832        let mut next = Vec::new();
2833        // For building a depth first search order of the tree.
2834        let mut dfs = Vec::new();
2835
2836        // First we build a depth first search order of the tree.
2837        next.extend(value.children.iter());
2838        dfs.push(&value);
2839        while let Some(value) = next.pop() {
2840            dfs.push(value);
2841            next.extend(value.children.iter());
2842        }
2843
2844        // Using depth first we build the new tree.
2845        let mut nodes = Vec::new();
2846        while let Some(value) = dfs.pop() {
2847            let mut children = Vec::new();
2848            for _ in 0..value.children.len() {
2849                // If a node have children, they should already be pushed and this is safe.
2850                children.push(nodes.pop().require()?);
2851            }
2852
2853            let node = Self {
2854                block_hash: value.block_hash.clone().require()?.try_into()?,
2855                children,
2856            };
2857            nodes.push(node)
2858        }
2859
2860        // Only one node should be left and is the root of the tree.
2861        let root = nodes.pop().require()?;
2862        Ok(root)
2863    }
2864}
2865
2866impl TryFrom<election_info::Baker> for super::types::BirkBaker {
2867    type Error = tonic::Status;
2868
2869    fn try_from(info: election_info::Baker) -> Result<Self, Self::Error> {
2870        Ok(Self {
2871            baker_id:            info.baker.require()?.into(),
2872            baker_lottery_power: info.lottery_power,
2873            baker_account:       info.account.require()?.try_into()?,
2874        })
2875    }
2876}
2877
2878impl TryFrom<ElectionInfo> for super::types::BirkParameters {
2879    type Error = tonic::Status;
2880
2881    fn try_from(info: ElectionInfo) -> Result<Self, Self::Error> {
2882        Ok(Self {
2883            election_difficulty: info.election_difficulty.map(|x| x.try_into()).transpose()?,
2884            election_nonce:      info.election_nonce.require()?.try_into()?,
2885            bakers:              info
2886                .baker_election_info
2887                .into_iter()
2888                .map(|c| c.try_into())
2889                .collect::<Result<_, _>>()?,
2890        })
2891    }
2892}
2893
2894impl TryFrom<block_special_event::AccountAmounts>
2895    for BTreeMap<super::AccountAddress, super::Amount>
2896{
2897    type Error = tonic::Status;
2898
2899    fn try_from(message: block_special_event::AccountAmounts) -> Result<Self, Self::Error> {
2900        fn mapper(
2901            entry: block_special_event::account_amounts::Entry,
2902        ) -> Result<(super::AccountAddress, super::Amount), tonic::Status> {
2903            Ok((
2904                entry.account.require()?.try_into()?,
2905                entry.amount.require()?.into(),
2906            ))
2907        }
2908
2909        message
2910            .entries
2911            .into_iter()
2912            .map(mapper)
2913            .collect::<Result<_, _>>()
2914    }
2915}
2916
2917impl TryFrom<BlockSpecialEvent> for super::types::SpecialTransactionOutcome {
2918    type Error = tonic::Status;
2919
2920    fn try_from(message: BlockSpecialEvent) -> Result<Self, Self::Error> {
2921        let event = match message.event.require()? {
2922            block_special_event::Event::BakingRewards(event) => Self::BakingRewards {
2923                baker_rewards: event.baker_rewards.require()?.try_into()?,
2924                remainder:     event.remainder.require()?.into(),
2925            },
2926            block_special_event::Event::Mint(event) => Self::Mint {
2927                mint_baking_reward:               event.mint_baking_reward.require()?.into(),
2928                mint_finalization_reward:         event.mint_finalization_reward.require()?.into(),
2929                mint_platform_development_charge: event
2930                    .mint_platform_development_charge
2931                    .require()?
2932                    .into(),
2933                foundation_account:               event.foundation_account.require()?.try_into()?,
2934            },
2935            block_special_event::Event::FinalizationRewards(event) => Self::FinalizationRewards {
2936                finalization_rewards: event.finalization_rewards.require()?.try_into()?,
2937                remainder:            event.remainder.require()?.into(),
2938            },
2939            block_special_event::Event::BlockReward(event) => Self::BlockReward {
2940                transaction_fees:   event.transaction_fees.require()?.into(),
2941                old_gas_account:    event.old_gas_account.require()?.into(),
2942                new_gas_account:    event.new_gas_account.require()?.into(),
2943                baker_reward:       event.baker_reward.require()?.into(),
2944                foundation_charge:  event.foundation_charge.require()?.into(),
2945                baker:              event.baker.require()?.try_into()?,
2946                foundation_account: event.foundation_account.require()?.try_into()?,
2947            },
2948            block_special_event::Event::PaydayFoundationReward(event) => {
2949                Self::PaydayFoundationReward {
2950                    foundation_account: event.foundation_account.require()?.try_into()?,
2951                    development_charge: event.development_charge.require()?.into(),
2952                }
2953            }
2954            block_special_event::Event::PaydayAccountReward(event) => Self::PaydayAccountReward {
2955                account:             event.account.require()?.try_into()?,
2956                transaction_fees:    event.transaction_fees.require()?.into(),
2957                baker_reward:        event.baker_reward.require()?.into(),
2958                finalization_reward: event.finalization_reward.require()?.into(),
2959            },
2960            block_special_event::Event::BlockAccrueReward(event) => Self::BlockAccrueReward {
2961                transaction_fees:  event.transaction_fees.require()?.into(),
2962                old_gas_account:   event.old_gas_account.require()?.into(),
2963                new_gas_account:   event.new_gas_account.require()?.into(),
2964                baker_reward:      event.baker_reward.require()?.into(),
2965                passive_reward:    event.passive_reward.require()?.into(),
2966                foundation_charge: event.foundation_charge.require()?.into(),
2967                baker_id:          event.baker.require()?.into(),
2968            },
2969            block_special_event::Event::PaydayPoolReward(event) => Self::PaydayPoolReward {
2970                pool_owner:          event.pool_owner.map(|b| b.into()),
2971                transaction_fees:    event.transaction_fees.require()?.into(),
2972                baker_reward:        event.baker_reward.require()?.into(),
2973                finalization_reward: event.finalization_reward.require()?.into(),
2974            },
2975            block_special_event::Event::ValidatorSuspended(event) => Self::ValidatorSuspended {
2976                baker_id: event.baker_id.require()?.into(),
2977                account:  event.account.require()?.try_into()?,
2978            },
2979            block_special_event::Event::ValidatorPrimedForSuspension(event) => {
2980                Self::ValidatorPrimedForSuspension {
2981                    baker_id: event.baker_id.require()?.into(),
2982                    account:  event.account.require()?.try_into()?,
2983                }
2984            }
2985        };
2986        Ok(event)
2987    }
2988}
2989
2990impl<K> TryFrom<HigherLevelKeys> for updates::HigherLevelAccessStructure<K> {
2991    type Error = tonic::Status;
2992
2993    fn try_from(message: HigherLevelKeys) -> Result<Self, Self::Error> {
2994        Ok(Self {
2995            keys:      message
2996                .keys
2997                .into_iter()
2998                .map(TryFrom::try_from)
2999                .collect::<Result<_, _>>()?,
3000            threshold: message.threshold.require()?.try_into()?,
3001            _phantom:  Default::default(),
3002        })
3003    }
3004}
3005
3006impl TryFrom<ProtocolUpdate> for updates::ProtocolUpdate {
3007    type Error = tonic::Status;
3008
3009    fn try_from(value: ProtocolUpdate) -> Result<Self, Self::Error> {
3010        let message = value.message;
3011        let specification_url = value.specification_url;
3012        let specification_hash = value.specification_hash.require()?.try_into()?;
3013        let specification_auxiliary_data = value.specification_auxiliary_data;
3014        Ok(Self {
3015            message,
3016            specification_url,
3017            specification_hash,
3018            specification_auxiliary_data,
3019        })
3020    }
3021}
3022
3023impl TryFrom<ExchangeRate> for base::ExchangeRate {
3024    type Error = tonic::Status;
3025
3026    fn try_from(value: ExchangeRate) -> Result<Self, Self::Error> {
3027        let ratio = value.value.require()?;
3028        Self::new(ratio.numerator, ratio.denominator)
3029            .ok_or_else(|| tonic::Status::internal("Not a valid exchange rate."))
3030    }
3031}
3032
3033impl TryFrom<MintDistributionCpv0> for base::MintDistributionV0 {
3034    type Error = tonic::Status;
3035
3036    fn try_from(value: MintDistributionCpv0) -> Result<Self, Self::Error> {
3037        Ok(Self {
3038            mint_per_slot:       value.mint_per_slot.require()?.try_into()?,
3039            baking_reward:       value.baking_reward.require()?.into(),
3040            finalization_reward: value.finalization_reward.require()?.into(),
3041        })
3042    }
3043}
3044
3045impl TryFrom<MintDistributionCpv1> for base::MintDistributionV1 {
3046    type Error = tonic::Status;
3047
3048    fn try_from(value: MintDistributionCpv1) -> Result<Self, Self::Error> {
3049        Ok(Self {
3050            baking_reward:       value.baking_reward.require()?.into(),
3051            finalization_reward: value.finalization_reward.require()?.into(),
3052        })
3053    }
3054}
3055
3056impl TryFrom<TransactionFeeDistribution> for updates::TransactionFeeDistribution {
3057    type Error = tonic::Status;
3058
3059    fn try_from(value: TransactionFeeDistribution) -> Result<Self, Self::Error> {
3060        Ok(Self {
3061            baker:       value.baker.require()?.into(),
3062            gas_account: value.gas_account.require()?.into(),
3063        })
3064    }
3065}
3066
3067impl TryFrom<GasRewards> for updates::GASRewards {
3068    type Error = tonic::Status;
3069
3070    fn try_from(value: GasRewards) -> Result<Self, Self::Error> {
3071        Ok(Self {
3072            baker:              value.baker.require()?.into(),
3073            finalization_proof: value.finalization_proof.require()?.into(),
3074            account_creation:   value.account_creation.require()?.into(),
3075            chain_update:       value.chain_update.require()?.into(),
3076        })
3077    }
3078}
3079
3080impl TryFrom<GasRewardsCpv2> for updates::GASRewardsV1 {
3081    type Error = tonic::Status;
3082
3083    fn try_from(value: GasRewardsCpv2) -> Result<Self, Self::Error> {
3084        Ok(Self {
3085            baker:            value.baker.require()?.into(),
3086            account_creation: value.account_creation.require()?.into(),
3087            chain_update:     value.chain_update.require()?.into(),
3088        })
3089    }
3090}
3091
3092impl TryFrom<TimeoutParameters> for updates::TimeoutParameters {
3093    type Error = tonic::Status;
3094
3095    fn try_from(value: TimeoutParameters) -> Result<Self, Self::Error> {
3096        let base = value.timeout_base.require()?.into();
3097        let increase = value.timeout_increase.require()?.try_into()?;
3098        let decrease = value.timeout_decrease.require()?.try_into()?;
3099        Self::new(base, increase, decrease).map_err(|err| tonic::Status::internal(err.to_string()))
3100    }
3101}
3102
3103impl TryFrom<Ratio> for concordium_base::common::types::Ratio {
3104    type Error = tonic::Status;
3105
3106    fn try_from(value: Ratio) -> Result<Self, Self::Error> {
3107        Self::new(value.numerator, value.denominator)
3108            .map_err(|err| tonic::Status::internal(err.to_string()))
3109    }
3110}
3111
3112impl TryFrom<FinalizationCommitteeParameters> for updates::FinalizationCommitteeParameters {
3113    type Error = tonic::Status;
3114
3115    fn try_from(value: FinalizationCommitteeParameters) -> Result<Self, Self::Error> {
3116        Ok(Self {
3117            min_finalizers: value.minimum_finalizers,
3118            max_finalizers: value.maximum_finalizers,
3119            finalizers_relative_stake_threshold: value
3120                .finalizer_relative_stake_threshold
3121                .require()?
3122                .into(),
3123        })
3124    }
3125}
3126
3127impl TryFrom<ValidatorScoreParameters> for updates::ValidatorScoreParameters {
3128    type Error = tonic::Status;
3129
3130    fn try_from(value: ValidatorScoreParameters) -> Result<Self, Self::Error> {
3131        Ok(Self {
3132            max_missed_rounds: value.maximum_missed_rounds,
3133        })
3134    }
3135}
3136
3137impl TryFrom<PoolParametersCpv1> for updates::PoolParameters {
3138    type Error = tonic::Status;
3139
3140    fn try_from(value: PoolParametersCpv1) -> Result<Self, Self::Error> {
3141        Ok(Self {
3142            passive_finalization_commission: value
3143                .passive_finalization_commission
3144                .require()?
3145                .into(),
3146            passive_baking_commission:       value.passive_baking_commission.require()?.into(),
3147            passive_transaction_commission:  value.passive_transaction_commission.require()?.into(),
3148            commission_bounds:               value.commission_bounds.require()?.try_into()?,
3149            minimum_equity_capital:          value.minimum_equity_capital.require()?.into(),
3150            capital_bound:                   value.capital_bound.require()?.try_into()?,
3151            leverage_bound:                  value.leverage_bound.require()?.try_into()?,
3152        })
3153    }
3154}
3155
3156impl TryFrom<LeverageFactor> for super::types::LeverageFactor {
3157    type Error = tonic::Status;
3158
3159    fn try_from(value: LeverageFactor) -> Result<Self, Self::Error> {
3160        let ratio = value.value.require()?;
3161        Self::new(ratio.numerator, ratio.denominator)
3162            .ok_or_else(|| tonic::Status::internal("Invalid leverage factor."))
3163    }
3164}
3165
3166impl TryFrom<CommissionRanges> for super::types::CommissionRanges {
3167    type Error = tonic::Status;
3168
3169    fn try_from(value: CommissionRanges) -> Result<Self, Self::Error> {
3170        Ok(Self {
3171            finalization: value.finalization.require()?.try_into()?,
3172            baking:       value.baking.require()?.try_into()?,
3173            transaction:  value.transaction.require()?.try_into()?,
3174        })
3175    }
3176}
3177
3178impl TryFrom<BakerStakeThreshold> for updates::BakerParameters {
3179    type Error = tonic::Status;
3180
3181    fn try_from(value: BakerStakeThreshold) -> Result<Self, Self::Error> {
3182        Ok(Self {
3183            minimum_threshold_for_baking: value.baker_stake_threshold.require()?.into(),
3184        })
3185    }
3186}
3187
3188impl TryFrom<CooldownParametersCpv1> for updates::CooldownParameters {
3189    type Error = tonic::Status;
3190
3191    fn try_from(value: CooldownParametersCpv1) -> Result<Self, Self::Error> {
3192        Ok(Self {
3193            pool_owner_cooldown: value.pool_owner_cooldown.require()?.into(),
3194            delegator_cooldown:  value.delegator_cooldown.require()?.into(),
3195        })
3196    }
3197}
3198
3199impl TryFrom<TimeParametersCpv1> for updates::TimeParameters {
3200    type Error = tonic::Status;
3201
3202    fn try_from(value: TimeParametersCpv1) -> Result<Self, Self::Error> {
3203        Ok(Self {
3204            reward_period_length: value.reward_period_length.require()?.try_into()?,
3205            mint_per_payday:      value.mint_per_payday.require()?.try_into()?,
3206        })
3207    }
3208}
3209
3210impl TryFrom<RewardPeriodLength> for updates::RewardPeriodLength {
3211    type Error = tonic::Status;
3212
3213    fn try_from(value: RewardPeriodLength) -> Result<Self, Self::Error> {
3214        Ok(Self::from(base::Epoch::from(value.value.require()?)))
3215    }
3216}
3217
3218impl From<Epoch> for base::Epoch {
3219    fn from(value: Epoch) -> Self { Self { epoch: value.value } }
3220}
3221
3222impl From<Round> for base::Round {
3223    fn from(value: Round) -> Self { Self { round: value.value } }
3224}
3225
3226impl TryFrom<PendingUpdate> for super::types::queries::PendingUpdate {
3227    type Error = tonic::Status;
3228
3229    fn try_from(message: PendingUpdate) -> Result<Self, Self::Error> {
3230        use super::types::queries::PendingUpdateEffect;
3231        let effective_time = message.effective_time.require()?.into();
3232        match message.effect.require()? {
3233            pending_update::Effect::RootKeys(e) => {
3234                let hk = e.try_into()?;
3235                Ok(Self {
3236                    effective_time,
3237                    effect: PendingUpdateEffect::RootKeys(hk),
3238                })
3239            }
3240            pending_update::Effect::Level1Keys(l1) => {
3241                let l1 = l1.try_into()?;
3242                Ok(Self {
3243                    effective_time,
3244                    effect: PendingUpdateEffect::Level1Keys(l1),
3245                })
3246            }
3247            pending_update::Effect::Level2KeysCpv0(l2) => {
3248                let l2 = l2.try_into()?;
3249                Ok(Self {
3250                    effective_time,
3251                    effect: PendingUpdateEffect::Level2KeysCPV0(l2),
3252                })
3253            }
3254            pending_update::Effect::Level2KeysCpv1(l2) => {
3255                let l2 = l2.try_into()?;
3256                Ok(Self {
3257                    effective_time,
3258                    effect: PendingUpdateEffect::Level2KeysCPV1(l2),
3259                })
3260            }
3261            pending_update::Effect::Protocol(p) => {
3262                let p = p.try_into()?;
3263                Ok(Self {
3264                    effective_time,
3265                    effect: PendingUpdateEffect::Protocol(p),
3266                })
3267            }
3268            pending_update::Effect::ElectionDifficulty(ed) => Ok(Self {
3269                effective_time,
3270                effect: PendingUpdateEffect::ElectionDifficulty(ed.try_into()?),
3271            }),
3272            pending_update::Effect::EuroPerEnergy(ee) => Ok(Self {
3273                effective_time,
3274                effect: PendingUpdateEffect::EuroPerEnergy(ee.try_into()?),
3275            }),
3276            pending_update::Effect::MicroCcdPerEuro(mpe) => Ok(Self {
3277                effective_time,
3278                effect: PendingUpdateEffect::MicroCcdPerEnergy(mpe.try_into()?),
3279            }),
3280            pending_update::Effect::FoundationAccount(fa) => Ok(Self {
3281                effective_time,
3282                effect: PendingUpdateEffect::FoundationAccount(fa.try_into()?),
3283            }),
3284            pending_update::Effect::MintDistributionCpv0(md) => Ok(Self {
3285                effective_time,
3286                effect: PendingUpdateEffect::MintDistributionV0(md.try_into()?),
3287            }),
3288            pending_update::Effect::MintDistributionCpv1(md) => Ok(Self {
3289                effective_time,
3290                effect: PendingUpdateEffect::MintDistributionV1(md.try_into()?),
3291            }),
3292            pending_update::Effect::TransactionFeeDistribution(tfd) => Ok(Self {
3293                effective_time,
3294                effect: PendingUpdateEffect::TransactionFeeDistribution(tfd.try_into()?),
3295            }),
3296            pending_update::Effect::GasRewards(gr) => Ok(Self {
3297                effective_time,
3298                effect: PendingUpdateEffect::GasRewards(gr.try_into()?),
3299            }),
3300            pending_update::Effect::PoolParametersCpv0(pp) => Ok(Self {
3301                effective_time,
3302                effect: PendingUpdateEffect::PoolParametersV0(pp.try_into()?),
3303            }),
3304            pending_update::Effect::PoolParametersCpv1(pp) => Ok(Self {
3305                effective_time,
3306                effect: PendingUpdateEffect::PoolParametersV1(pp.try_into()?),
3307            }),
3308            pending_update::Effect::AddAnonymityRevoker(aar) => Ok(Self {
3309                effective_time,
3310                effect: PendingUpdateEffect::AddAnonymityRevoker(aar.try_into()?),
3311            }),
3312            pending_update::Effect::AddIdentityProvider(aidp) => Ok(Self {
3313                effective_time,
3314                effect: PendingUpdateEffect::AddIdentityProvider(Box::new(aidp.try_into()?)),
3315            }),
3316            pending_update::Effect::CooldownParameters(cdp) => Ok(Self {
3317                effective_time,
3318                effect: PendingUpdateEffect::CooldownParameters(cdp.try_into()?),
3319            }),
3320            pending_update::Effect::TimeParameters(tp) => Ok(Self {
3321                effective_time,
3322                effect: PendingUpdateEffect::TimeParameters(tp.try_into()?),
3323            }),
3324            pending_update::Effect::GasRewardsCpv2(update) => Ok(Self {
3325                effective_time,
3326                effect: PendingUpdateEffect::GasRewardsV1(update.try_into()?),
3327            }),
3328            pending_update::Effect::TimeoutParameters(update) => Ok(Self {
3329                effective_time,
3330                effect: PendingUpdateEffect::TimeoutParameters(update.try_into()?),
3331            }),
3332            pending_update::Effect::MinBlockTime(update) => Ok(Self {
3333                effective_time,
3334                effect: PendingUpdateEffect::MinBlockTime(update.into()),
3335            }),
3336            pending_update::Effect::BlockEnergyLimit(update) => Ok(Self {
3337                effective_time,
3338                effect: PendingUpdateEffect::BlockEnergyLimit(update.into()),
3339            }),
3340            pending_update::Effect::FinalizationCommitteeParameters(update) => Ok(Self {
3341                effective_time,
3342                effect: PendingUpdateEffect::FinalizationCommitteeParameters(update.try_into()?),
3343            }),
3344            pending_update::Effect::ValidatorScoreParameters(update) => Ok(Self {
3345                effective_time,
3346                effect: PendingUpdateEffect::ValidatorScoreParameters(update.try_into()?),
3347            }),
3348        }
3349    }
3350}
3351
3352impl From<SequenceNumber> for super::types::UpdateSequenceNumber {
3353    fn from(message: SequenceNumber) -> Self { message.value.into() }
3354}
3355
3356impl From<UpdateSequenceNumber> for super::types::UpdateSequenceNumber {
3357    fn from(message: UpdateSequenceNumber) -> Self { message.value.into() }
3358}
3359
3360impl TryFrom<NextUpdateSequenceNumbers> for super::types::queries::NextUpdateSequenceNumbers {
3361    type Error = tonic::Status;
3362
3363    fn try_from(message: NextUpdateSequenceNumbers) -> Result<Self, Self::Error> {
3364        Ok(Self {
3365            root_keys: message.root_keys.require()?.into(),
3366            level_1_keys: message.level1_keys.require()?.into(),
3367            level_2_keys: message.level2_keys.require()?.into(),
3368            protocol: message.protocol.require()?.into(),
3369            election_difficulty: message.election_difficulty.require()?.into(),
3370            euro_per_energy: message.euro_per_energy.require()?.into(),
3371            micro_ccd_per_euro: message.micro_ccd_per_euro.require()?.into(),
3372            foundation_account: message.foundation_account.require()?.into(),
3373            mint_distribution: message.mint_distribution.require()?.into(),
3374            transaction_fee_distribution: message.transaction_fee_distribution.require()?.into(),
3375            gas_rewards: message.gas_rewards.require()?.into(),
3376            pool_parameters: message.pool_parameters.require()?.into(),
3377            add_anonymity_revoker: message.add_anonymity_revoker.require()?.into(),
3378            add_identity_provider: message.add_identity_provider.require()?.into(),
3379            cooldown_parameters: message.cooldown_parameters.require()?.into(),
3380            time_parameters: message.time_parameters.require()?.into(),
3381            timeout_parameters: message.timeout_parameters.require()?.into(),
3382            min_block_time: message.min_block_time.require()?.into(),
3383            block_energy_limit: message.block_energy_limit.require()?.into(),
3384            finalization_committee_parameters: message
3385                .finalization_committee_parameters
3386                .require()?
3387                .into(),
3388            validator_score_parameters: message
3389                .validator_score_parameters
3390                .map(Into::into)
3391                .unwrap_or_default(),
3392            protocol_level_tokens: message
3393                .protocol_level_tokens
3394                .map(Into::into)
3395                .unwrap_or_default(),
3396        })
3397    }
3398}
3399
3400impl TryFrom<QuorumSignature> for super::types::block_certificates::QuorumSignature {
3401    type Error = tonic::Status;
3402
3403    fn try_from(message: QuorumSignature) -> Result<Self, Self::Error> { consume(&message.value) }
3404}
3405
3406impl TryFrom<QuorumCertificate> for super::types::block_certificates::QuorumCertificate {
3407    type Error = tonic::Status;
3408
3409    fn try_from(message: QuorumCertificate) -> Result<Self, Self::Error> {
3410        Ok(Self {
3411            block_hash:          message.block_hash.require()?.try_into()?,
3412            round:               message.round.require()?.into(),
3413            epoch:               message.epoch.require()?.into(),
3414            aggregate_signature: message.aggregate_signature.require()?.try_into()?,
3415            signatories:         message
3416                .signatories
3417                .into_iter()
3418                .map(From::from)
3419                .collect::<BTreeSet<super::types::BakerId>>(),
3420        })
3421    }
3422}
3423
3424impl TryFrom<SuccessorProof> for super::hashes::SuccessorProof {
3425    type Error = tonic::Status;
3426
3427    fn try_from(message: SuccessorProof) -> Result<Self, Self::Error> {
3428        match message.value.try_into() {
3429            Ok(hash) => Ok(Self::new(hash)),
3430            Err(_) => Err(tonic::Status::internal(
3431                "Unexpected successor proof format.",
3432            )),
3433        }
3434    }
3435}
3436
3437impl TryFrom<EpochFinalizationEntry> for super::types::block_certificates::EpochFinalizationEntry {
3438    type Error = tonic::Status;
3439
3440    fn try_from(message: EpochFinalizationEntry) -> Result<Self, Self::Error> {
3441        Ok(Self {
3442            finalized_qc:    message.finalized_qc.require()?.try_into()?,
3443            successor_qc:    message.successor_qc.require()?.try_into()?,
3444            successor_proof: message.successor_proof.require()?.try_into()?,
3445        })
3446    }
3447}
3448
3449impl TryFrom<FinalizerRound> for super::types::block_certificates::FinalizerRound {
3450    type Error = tonic::Status;
3451
3452    fn try_from(message: FinalizerRound) -> Result<Self, Self::Error> {
3453        Ok(Self {
3454            round:      message.round.require()?.into(),
3455            finalizers: message
3456                .finalizers
3457                .into_iter()
3458                .map(From::from)
3459                .collect::<Vec<super::types::BakerId>>(),
3460        })
3461    }
3462}
3463
3464impl TryFrom<TimeoutSignature> for super::types::block_certificates::TimeoutSignature {
3465    type Error = tonic::Status;
3466
3467    fn try_from(message: TimeoutSignature) -> Result<Self, Self::Error> { consume(&message.value) }
3468}
3469
3470impl TryFrom<TimeoutCertificate> for super::types::block_certificates::TimeoutCertificate {
3471    type Error = tonic::Status;
3472
3473    fn try_from(message: TimeoutCertificate) -> Result<Self, Self::Error> {
3474        Ok(
3475            Self {
3476                round:                  message.round.require()?.into(),
3477                min_epoch:              message.min_epoch.require()?.into(),
3478                qc_rounds_first_epoch:
3479                    message
3480                        .qc_rounds_first_epoch
3481                        .into_iter()
3482                        .map(TryFrom::try_from)
3483                        .collect::<Result<
3484                            Vec<super::types::block_certificates::FinalizerRound>,
3485                            tonic::Status,
3486                        >>()?,
3487                qc_rounds_second_epoch:
3488                    message
3489                        .qc_rounds_second_epoch
3490                        .into_iter()
3491                        .map(TryFrom::try_from)
3492                        .collect::<Result<
3493                            Vec<super::types::block_certificates::FinalizerRound>,
3494                            tonic::Status,
3495                        >>()?,
3496                aggregate_signature:    message.aggregate_signature.require()?.try_into()?,
3497            },
3498        )
3499    }
3500}
3501
3502impl TryFrom<BlockCertificates> for super::types::block_certificates::BlockCertificates {
3503    type Error = tonic::Status;
3504
3505    fn try_from(message: BlockCertificates) -> Result<Self, Self::Error> {
3506        Ok(Self {
3507            quorum_certificate:       message
3508                .quorum_certificate
3509                .map(TryFrom::try_from)
3510                .transpose()?,
3511            timeout_certificate:      message
3512                .timeout_certificate
3513                .map(TryFrom::try_from)
3514                .transpose()?,
3515            epoch_finalization_entry: message
3516                .epoch_finalization_entry
3517                .map(TryFrom::try_from)
3518                .transpose()?,
3519        })
3520    }
3521}
3522
3523impl TryFrom<WinningBaker> for super::types::WinningBaker {
3524    type Error = tonic::Status;
3525
3526    fn try_from(wb: WinningBaker) -> Result<Self, Self::Error> {
3527        Ok(Self {
3528            round:   wb.round.require()?.value.into(),
3529            winner:  super::types::BakerId {
3530                id: wb.winner.require()?.value.into(),
3531            },
3532            present: wb.present,
3533        })
3534    }
3535}
3536
3537impl TryFrom<AccountPending> for super::types::AccountPending {
3538    type Error = tonic::Status;
3539
3540    fn try_from(pending: AccountPending) -> Result<Self, Self::Error> {
3541        Ok(Self {
3542            account_index:   pending.account_index.require()?.into(),
3543            first_timestamp: pending.first_timestamp.require()?.into(),
3544        })
3545    }
3546}
3547
3548impl TryFrom<BakerRewardPeriodInfo> for super::types::BakerRewardPeriodInfo {
3549    type Error = tonic::Status;
3550
3551    fn try_from(message: BakerRewardPeriodInfo) -> Result<Self, Self::Error> {
3552        Ok(Self {
3553            baker:             message.baker.require()?.try_into()?,
3554            effective_stake:   message.effective_stake.require()?.into(),
3555            commission_rates:  message.commission_rates.require()?.try_into()?,
3556            equity_capital:    message.equity_capital.require()?.into(),
3557            delegated_capital: message.delegated_capital.require()?.into(),
3558            is_finalizer:      message.is_finalizer,
3559        })
3560    }
3561}
3562
3563impl From<FinalizerIndex> for super::types::block_certificates::raw::FinalizerIndex {
3564    fn from(value: FinalizerIndex) -> Self { Self { index: value.value } }
3565}
3566
3567impl TryFrom<QuorumMessage> for super::types::block_certificates::raw::QuorumMessage {
3568    type Error = tonic::Status;
3569
3570    fn try_from(message: QuorumMessage) -> Result<Self, Self::Error> {
3571        Ok(Self {
3572            signature: message.signature.require()?.try_into()?,
3573            block:     message.block.require()?.try_into()?,
3574            finalizer: message.finalizer.require()?.into(),
3575            round:     message.round.require()?.into(),
3576            epoch:     message.epoch.require()?.into(),
3577        })
3578    }
3579}
3580
3581impl TryFrom<RawQuorumCertificate> for super::types::block_certificates::raw::QuorumCertificate {
3582    type Error = tonic::Status;
3583
3584    fn try_from(value: RawQuorumCertificate) -> Result<Self, Self::Error> {
3585        Ok(Self {
3586            block_hash:          value.block_hash.require()?.try_into()?,
3587            round:               value.round.require()?.into(),
3588            epoch:               value.epoch.require()?.into(),
3589            aggregate_signature: value.aggregate_signature.require()?.try_into()?,
3590            signatories:         value.signatories.into_iter().map(From::from).collect(),
3591        })
3592    }
3593}
3594
3595impl TryFrom<RawTimeoutCertificate> for super::types::block_certificates::raw::TimeoutCertificate {
3596    type Error = tonic::Status;
3597
3598    fn try_from(value: RawTimeoutCertificate) -> Result<Self, Self::Error> {
3599        Ok(Self {
3600            round:                  value.round.require()?.into(),
3601            min_epoch:              value.min_epoch.require()?.into(),
3602            qc_rounds_first_epoch:  value
3603                .qc_rounds_first_epoch
3604                .into_iter()
3605                .map(TryFrom::try_from)
3606                .collect::<Result<_, _>>()?,
3607            qc_rounds_second_epoch: value
3608                .qc_rounds_second_epoch
3609                .into_iter()
3610                .map(TryFrom::try_from)
3611                .collect::<Result<_, _>>()?,
3612            aggregate_signature:    value.aggregate_signature.require()?.try_into()?,
3613        })
3614    }
3615}
3616
3617impl TryFrom<RawFinalizerRound> for super::types::block_certificates::raw::FinalizerRound {
3618    type Error = tonic::Status;
3619
3620    fn try_from(value: RawFinalizerRound) -> Result<Self, Self::Error> {
3621        Ok(Self {
3622            round:      value.round.require()?.into(),
3623            finalizers: value.finalizers.into_iter().map(From::from).collect(),
3624        })
3625    }
3626}
3627
3628impl TryFrom<BlockSignature> for super::types::block_certificates::raw::BlockSignature {
3629    type Error = tonic::Status;
3630
3631    fn try_from(message: BlockSignature) -> Result<Self, Self::Error> { consume(&message.value) }
3632}
3633
3634impl TryFrom<TimeoutMessage> for super::types::block_certificates::raw::TimeoutMessage {
3635    type Error = tonic::Status;
3636
3637    fn try_from(value: TimeoutMessage) -> Result<Self, Self::Error> {
3638        Ok(Self {
3639            finalizer:          value.finalizer.require()?.into(),
3640            round:              value.round.require()?.into(),
3641            epoch:              value.epoch.require()?.into(),
3642            quorum_certificate: value.quorum_certificate.require()?.try_into()?,
3643            signature:          value.signature.require()?.try_into()?,
3644            message_signature:  value.message_signature.require()?.try_into()?,
3645        })
3646    }
3647}
3648
3649impl TryFrom<RawFinalizationEntry> for super::types::block_certificates::raw::FinalizationEntry {
3650    type Error = tonic::Status;
3651
3652    fn try_from(value: RawFinalizationEntry) -> Result<Self, Self::Error> {
3653        Ok(Self {
3654            finalized_qc:    value.finalized_qc.require()?.try_into()?,
3655            successor_qc:    value.successor_qc.require()?.try_into()?,
3656            successor_proof: value.successor_proof.require()?.try_into()?,
3657        })
3658    }
3659}
3660
3661impl TryFrom<TimeoutMessages> for super::types::block_certificates::raw::TimeoutMessages {
3662    type Error = tonic::Status;
3663
3664    fn try_from(value: TimeoutMessages) -> Result<Self, Self::Error> {
3665        Ok(Self {
3666            first_epoch:           value.first_epoch.require()?.into(),
3667            first_epoch_timeouts:  value
3668                .first_epoch_timeouts
3669                .into_iter()
3670                .map(TryFrom::try_from)
3671                .collect::<Result<_, _>>()?,
3672            second_epoch_timeouts: value
3673                .second_epoch_timeouts
3674                .into_iter()
3675                .map(TryFrom::try_from)
3676                .collect::<Result<_, _>>()?,
3677        })
3678    }
3679}
3680
3681impl TryFrom<PersistentRoundStatus> for super::types::queries::PersistentRoundStatus {
3682    type Error = tonic::Status;
3683
3684    fn try_from(value: PersistentRoundStatus) -> Result<Self, Self::Error> {
3685        Ok(Self {
3686            last_signed_quorum_message:  value
3687                .last_signed_quorum_message
3688                .map(TryFrom::try_from)
3689                .transpose()?,
3690            last_signed_timeout_message: value
3691                .last_signed_timeout_message
3692                .map(TryFrom::try_from)
3693                .transpose()?,
3694            last_baked_round:            value.last_baked_round.require()?.into(),
3695            latest_timeout:              value.latest_timeout.map(TryFrom::try_from).transpose()?,
3696        })
3697    }
3698}
3699
3700impl TryFrom<RoundTimeout> for super::types::queries::RoundTimeout {
3701    type Error = tonic::Status;
3702
3703    fn try_from(value: RoundTimeout) -> Result<Self, Self::Error> {
3704        Ok(Self {
3705            timeout_certificate: value.timeout_certificate.require()?.try_into()?,
3706            quorum_certificate:  value.quorum_certificate.require()?.try_into()?,
3707        })
3708    }
3709}
3710
3711impl TryFrom<RoundStatus> for super::types::queries::RoundStatus {
3712    type Error = tonic::Status;
3713
3714    fn try_from(value: RoundStatus) -> Result<Self, Self::Error> {
3715        Ok(Self {
3716            current_round:                 value.current_round.require()?.into(),
3717            highest_certified_block:       value.highest_certified_block.require()?.try_into()?,
3718            previous_round_timeout:        value
3719                .previous_round_timeout
3720                .map(TryFrom::try_from)
3721                .transpose()?,
3722            round_eligible_to_bake:        value.round_eligible_to_bake,
3723            current_epoch:                 value.current_epoch.require()?.into(),
3724            last_epoch_finalization_entry: value
3725                .last_epoch_finalization_entry
3726                .map(TryFrom::try_from)
3727                .transpose()?,
3728            current_timeout:               value.current_timeout.require()?.into(),
3729        })
3730    }
3731}
3732
3733impl TryFrom<BlockTableSummary> for super::types::queries::BlockTableSummary {
3734    type Error = tonic::Status;
3735
3736    fn try_from(value: BlockTableSummary) -> Result<Self, Self::Error> {
3737        Ok(Self {
3738            dead_block_cache_size: value.dead_block_cache_size,
3739            live_blocks:           value
3740                .live_blocks
3741                .into_iter()
3742                .map(TryFrom::try_from)
3743                .collect::<Result<_, _>>()?,
3744        })
3745    }
3746}
3747
3748impl TryFrom<RoundExistingBlock> for super::types::queries::RoundExistingBlock {
3749    type Error = tonic::Status;
3750
3751    fn try_from(value: RoundExistingBlock) -> Result<Self, Self::Error> {
3752        Ok(Self {
3753            round: value.round.require()?.into(),
3754            baker: value.baker.require()?.into(),
3755            block: value.block.require()?.try_into()?,
3756        })
3757    }
3758}
3759
3760impl TryFrom<RoundExistingQc> for super::types::queries::RoundExistingQC {
3761    type Error = tonic::Status;
3762
3763    fn try_from(value: RoundExistingQc) -> Result<Self, Self::Error> {
3764        Ok(Self {
3765            round: value.round.require()?.into(),
3766            epoch: value.epoch.require()?.into(),
3767        })
3768    }
3769}
3770
3771impl TryFrom<FullBakerInfo> for super::types::queries::FullBakerInfo {
3772    type Error = tonic::Status;
3773
3774    fn try_from(value: FullBakerInfo) -> Result<Self, Self::Error> {
3775        Ok(Self {
3776            baker_identity:         value.baker_identity.require()?.into(),
3777            election_verify_key:    value.election_verify_key.require()?.try_into()?,
3778            signature_verify_key:   value.signature_verify_key.require()?.try_into()?,
3779            aggregation_verify_key: value.aggregation_verify_key.require()?.try_into()?,
3780            stake:                  value.stake.require()?.into(),
3781        })
3782    }
3783}
3784
3785impl TryFrom<FinalizationCommitteeHash> for concordium_base::hashes::FinalizationCommitteeHash {
3786    type Error = tonic::Status;
3787
3788    fn try_from(value: FinalizationCommitteeHash) -> Result<Self, Self::Error> {
3789        match value.value.try_into() {
3790            Ok(hash) => Ok(Self::new(hash)),
3791            Err(_) => Err(tonic::Status::internal(
3792                "Unexpected finalization committee hash format.",
3793            )),
3794        }
3795    }
3796}
3797
3798impl TryFrom<BakersAndFinalizers> for super::types::queries::BakersAndFinalizers {
3799    type Error = tonic::Status;
3800
3801    fn try_from(value: BakersAndFinalizers) -> Result<Self, Self::Error> {
3802        Ok(Self {
3803            bakers: value
3804                .bakers
3805                .into_iter()
3806                .map(TryFrom::try_from)
3807                .collect::<Result<_, _>>()?,
3808            finalizers: value.finalizers.into_iter().map(From::from).collect(),
3809            baker_total_stake: value.baker_total_stake.require()?.into(),
3810            finalizer_total_stake: value.finalizer_total_stake.require()?.into(),
3811            finalization_committee_hash: value.finalization_committee_hash.require()?.try_into()?,
3812        })
3813    }
3814}
3815
3816impl TryFrom<EpochBakers> for super::types::queries::EpochBakers {
3817    type Error = tonic::Status;
3818
3819    fn try_from(value: EpochBakers) -> Result<Self, Self::Error> {
3820        Ok(Self {
3821            previous_epoch_bakers: value.previous_epoch_bakers.require()?.try_into()?,
3822            current_epoch_bakers:  value
3823                .current_epoch_bakers
3824                .map(TryFrom::try_from)
3825                .transpose()?,
3826            next_epoch_bakers:     value.next_epoch_bakers.map(TryFrom::try_from).transpose()?,
3827            next_payday:           value.next_payday.require()?.into(),
3828        })
3829    }
3830}
3831
3832impl TryFrom<BranchBlocks> for Vec<super::BlockHash> {
3833    type Error = tonic::Status;
3834
3835    fn try_from(value: BranchBlocks) -> Result<Self, Self::Error> {
3836        value
3837            .blocks_at_branch_height
3838            .into_iter()
3839            .map(TryFrom::try_from)
3840            .collect()
3841    }
3842}
3843
3844impl TryFrom<ConsensusDetailedStatus> for super::types::queries::ConsensusDetailedStatus {
3845    type Error = tonic::Status;
3846
3847    fn try_from(value: ConsensusDetailedStatus) -> Result<Self, Self::Error> {
3848        Ok(Self {
3849            genesis_block: value.genesis_block.require()?.try_into()?,
3850            persistent_round_status: value.persistent_round_status.require()?.try_into()?,
3851            round_status: value.round_status.require()?.try_into()?,
3852            non_finalized_transaction_count: value.non_finalized_transaction_count,
3853            transaction_table_purge_counter: value.transaction_table_purge_counter,
3854            block_table: value.block_table.require()?.try_into()?,
3855            branches: value
3856                .branches
3857                .into_iter()
3858                .map(TryFrom::try_from)
3859                .collect::<Result<_, _>>()?,
3860            round_existing_blocks: value
3861                .round_existing_blocks
3862                .into_iter()
3863                .map(TryFrom::try_from)
3864                .collect::<Result<_, _>>()?,
3865            round_existing_qcs: value
3866                .round_existing_qcs
3867                .into_iter()
3868                .map(TryFrom::try_from)
3869                .collect::<Result<_, _>>()?,
3870            genesis_block_height: value.genesis_block_height.require()?.into(),
3871            last_finalized_block: value.last_finalized_block.require()?.try_into()?,
3872            last_finalized_block_height: value.last_finalized_block_height.require()?.into(),
3873            latest_finalization_entry: value
3874                .latest_finalization_entry
3875                .map(TryFrom::try_from)
3876                .transpose()?,
3877            epoch_bakers: value.epoch_bakers.require()?.try_into()?,
3878            timeout_messages: value.timeout_messages.map(TryFrom::try_from).transpose()?,
3879            terminal_block: value.terminal_block.map(TryFrom::try_from).transpose()?,
3880        })
3881    }
3882}
3883
3884#[cfg(test)]
3885mod test {
3886    use super::*;
3887
3888    #[test]
3889    fn test_try_from_branch() {
3890        use crate::types::queries::Branch as QBranch;
3891
3892        let from = Branch {
3893            block_hash: Some(BlockHash {
3894                value: vec![0u8; 32],
3895            }),
3896            children:   vec![
3897                Branch {
3898                    block_hash: Some(BlockHash {
3899                        value: vec![1u8; 32],
3900                    }),
3901                    children:   vec![],
3902                },
3903                Branch {
3904                    block_hash: Some(BlockHash {
3905                        value: vec![2u8; 32],
3906                    }),
3907                    children:   vec![Branch {
3908                        block_hash: Some(BlockHash {
3909                            value: vec![3u8; 32],
3910                        }),
3911                        children:   vec![],
3912                    }],
3913                },
3914            ],
3915        };
3916
3917        let to_target = QBranch {
3918            block_hash: [0u8; 32].into(),
3919            children:   vec![
3920                QBranch {
3921                    block_hash: [2u8; 32].into(),
3922                    children:   vec![QBranch {
3923                        block_hash: [3u8; 32].into(),
3924                        children:   vec![],
3925                    }],
3926                },
3927                QBranch {
3928                    block_hash: [1u8; 32].into(),
3929                    children:   vec![],
3930                },
3931            ],
3932        };
3933        let to = QBranch::try_from(from).expect("Failed to convert branch");
3934
3935        assert_eq!(to, to_target);
3936    }
3937}