Skip to main content

solana_storage_proto/
convert.rs

1use {
2    crate::{StoredExtendedRewards, StoredTransactionError, StoredTransactionStatusMeta},
3    solana_account_decoder::parse_token::{UiTokenAmount, real_number_string_trimmed},
4    solana_hash::{HASH_BYTES, Hash},
5    solana_instruction::error::InstructionError,
6    solana_message::{
7        MessageHeader, VersionedMessage,
8        compiled_instruction::CompiledInstruction,
9        legacy::Message as LegacyMessage,
10        v0::{self, LoadedAddresses, MessageAddressTableLookup},
11        v1,
12    },
13    solana_pubkey::Pubkey,
14    solana_signature::Signature,
15    solana_transaction::{Transaction, versioned::VersionedTransaction},
16    solana_transaction_context::transaction::TransactionReturnData,
17    solana_transaction_error::TransactionError,
18    solana_transaction_status::{
19        ConfirmedBlock, EntrySummary, InnerInstruction, InnerInstructions, Reward, RewardType,
20        RewardsAndNumPartitions, TransactionByAddrInfo, TransactionStatusMeta,
21        TransactionTokenBalance, TransactionWithStatusMeta, VersionedConfirmedBlock,
22        VersionedTransactionWithStatusMeta,
23    },
24    std::{
25        convert::{TryFrom, TryInto},
26        str::FromStr,
27    },
28    wincode::ReadError,
29};
30
31pub mod generated {
32    include!(concat!(
33        env!("OUT_DIR"),
34        "/solana.storage.confirmed_block.rs"
35    ));
36}
37
38pub mod tx_by_addr {
39    include!(concat!(
40        env!("OUT_DIR"),
41        "/solana.storage.transaction_by_addr.rs"
42    ));
43}
44
45pub mod entries {
46    include!(concat!(env!("OUT_DIR"), "/solana.storage.entries.rs"));
47}
48
49#[derive(Debug, thiserror::Error)]
50#[error("failed to decode {bytes:?}: {source}")]
51pub struct DecodeError {
52    pub bytes: Vec<u8>,
53    #[source]
54    pub source: ReadError,
55}
56
57impl From<Vec<Reward>> for generated::Rewards {
58    fn from(rewards: Vec<Reward>) -> Self {
59        Self {
60            rewards: rewards.into_iter().map(|r| r.into()).collect(),
61            num_partitions: None,
62        }
63    }
64}
65
66impl From<RewardsAndNumPartitions> for generated::Rewards {
67    fn from(input: RewardsAndNumPartitions) -> Self {
68        Self {
69            rewards: input.rewards.into_iter().map(|r| r.into()).collect(),
70            num_partitions: input.num_partitions.map(|n| n.into()),
71        }
72    }
73}
74
75impl From<generated::Rewards> for Vec<Reward> {
76    fn from(rewards: generated::Rewards) -> Self {
77        rewards.rewards.into_iter().map(|r| r.into()).collect()
78    }
79}
80
81impl From<generated::Rewards> for RewardsAndNumPartitions {
82    fn from(rewards: generated::Rewards) -> Self {
83        Self {
84            rewards: rewards.rewards.into_iter().map(|r| r.into()).collect(),
85            num_partitions: rewards
86                .num_partitions
87                .map(|generated::NumPartitions { num_partitions }| num_partitions),
88        }
89    }
90}
91
92impl From<StoredExtendedRewards> for generated::Rewards {
93    fn from(rewards: StoredExtendedRewards) -> Self {
94        Self {
95            rewards: rewards
96                .into_iter()
97                .map(|r| {
98                    let r: Reward = r.into();
99                    r.into()
100                })
101                .collect(),
102            num_partitions: None,
103        }
104    }
105}
106
107impl From<generated::Rewards> for StoredExtendedRewards {
108    fn from(rewards: generated::Rewards) -> Self {
109        rewards
110            .rewards
111            .into_iter()
112            .map(|r| {
113                let r: Reward = r.into();
114                r.into()
115            })
116            .collect()
117    }
118}
119
120impl From<Reward> for generated::Reward {
121    fn from(reward: Reward) -> Self {
122        Self {
123            pubkey: reward.pubkey,
124            lamports: reward.lamports,
125            post_balance: reward.post_balance,
126            reward_type: match reward.reward_type {
127                None => generated::RewardType::Unspecified,
128                Some(RewardType::Fee) => generated::RewardType::Fee,
129                Some(RewardType::Rent) => generated::RewardType::Rent,
130                Some(RewardType::Staking) => generated::RewardType::Staking,
131                Some(RewardType::Voting) => generated::RewardType::Voting,
132                Some(RewardType::DeactivatedStake) => generated::RewardType::DeactivatedStake,
133            } as i32,
134            commission: reward.commission.map(|c| c.to_string()).unwrap_or_default(),
135            commission_bps: reward
136                .commission_bps
137                .map(|bps| bps.to_string())
138                .unwrap_or_default(),
139        }
140    }
141}
142
143impl From<generated::Reward> for Reward {
144    fn from(reward: generated::Reward) -> Self {
145        Self {
146            pubkey: reward.pubkey,
147            lamports: reward.lamports,
148            post_balance: reward.post_balance,
149            reward_type: match reward.reward_type {
150                0 => None,
151                1 => Some(RewardType::Fee),
152                2 => Some(RewardType::Rent),
153                3 => Some(RewardType::Staking),
154                4 => Some(RewardType::Voting),
155                5 => Some(RewardType::DeactivatedStake),
156                _ => None,
157            },
158            commission: reward.commission.parse::<u8>().ok(),
159            commission_bps: reward.commission_bps.parse::<u16>().ok(),
160        }
161    }
162}
163
164impl From<u64> for generated::NumPartitions {
165    fn from(num_partitions: u64) -> Self {
166        Self { num_partitions }
167    }
168}
169
170impl From<VersionedConfirmedBlock> for generated::ConfirmedBlock {
171    fn from(confirmed_block: VersionedConfirmedBlock) -> Self {
172        let VersionedConfirmedBlock {
173            previous_blockhash,
174            blockhash,
175            parent_slot,
176            transactions,
177            rewards,
178            num_partitions,
179            block_time,
180            block_height,
181        } = confirmed_block;
182
183        Self {
184            previous_blockhash,
185            blockhash,
186            parent_slot,
187            transactions: transactions.into_iter().map(|tx| tx.into()).collect(),
188            rewards: rewards.into_iter().map(|r| r.into()).collect(),
189            num_partitions: num_partitions.map(Into::into),
190            block_time: block_time.map(|timestamp| generated::UnixTimestamp { timestamp }),
191            block_height: block_height.map(|block_height| generated::BlockHeight { block_height }),
192        }
193    }
194}
195
196impl TryFrom<generated::ConfirmedBlock> for ConfirmedBlock {
197    type Error = DecodeError;
198    fn try_from(
199        confirmed_block: generated::ConfirmedBlock,
200    ) -> std::result::Result<Self, Self::Error> {
201        let generated::ConfirmedBlock {
202            previous_blockhash,
203            blockhash,
204            parent_slot,
205            transactions,
206            rewards,
207            num_partitions,
208            block_time,
209            block_height,
210        } = confirmed_block;
211
212        Ok(Self {
213            previous_blockhash,
214            blockhash,
215            parent_slot,
216            transactions: transactions
217                .into_iter()
218                .map(|tx| tx.try_into())
219                .collect::<std::result::Result<Vec<_>, Self::Error>>()?,
220            rewards: rewards.into_iter().map(|r| r.into()).collect(),
221            num_partitions: num_partitions
222                .map(|generated::NumPartitions { num_partitions }| num_partitions),
223            block_time: block_time.map(|generated::UnixTimestamp { timestamp }| timestamp),
224            block_height: block_height.map(|generated::BlockHeight { block_height }| block_height),
225        })
226    }
227}
228
229impl From<TransactionWithStatusMeta> for generated::ConfirmedTransaction {
230    fn from(tx_with_meta: TransactionWithStatusMeta) -> Self {
231        match tx_with_meta {
232            TransactionWithStatusMeta::MissingMetadata(transaction) => Self {
233                transaction: Some(generated::Transaction::from(transaction)),
234                meta: None,
235            },
236            TransactionWithStatusMeta::Complete(tx_with_meta) => Self::from(tx_with_meta),
237        }
238    }
239}
240
241impl From<VersionedTransactionWithStatusMeta> for generated::ConfirmedTransaction {
242    fn from(value: VersionedTransactionWithStatusMeta) -> Self {
243        Self {
244            transaction: Some(value.transaction.into()),
245            meta: Some(value.meta.into()),
246        }
247    }
248}
249
250impl TryFrom<generated::ConfirmedTransaction> for TransactionWithStatusMeta {
251    type Error = DecodeError;
252    fn try_from(value: generated::ConfirmedTransaction) -> std::result::Result<Self, Self::Error> {
253        let meta = value.meta.map(|meta| meta.try_into()).transpose()?;
254        let transaction = value.transaction.expect("transaction is required").into();
255        Ok(match meta {
256            Some(meta) => Self::Complete(VersionedTransactionWithStatusMeta { transaction, meta }),
257            None => Self::MissingMetadata(
258                transaction
259                    .into_legacy_transaction()
260                    .expect("meta is required for versioned transactions"),
261            ),
262        })
263    }
264}
265
266impl From<Transaction> for generated::Transaction {
267    fn from(value: Transaction) -> Self {
268        Self {
269            signatures: value
270                .signatures
271                .into_iter()
272                .map(|signature| <Signature as AsRef<[u8]>>::as_ref(&signature).into())
273                .collect(),
274            message: Some(value.message.into()),
275        }
276    }
277}
278
279impl From<VersionedTransaction> for generated::Transaction {
280    fn from(value: VersionedTransaction) -> Self {
281        Self {
282            signatures: value
283                .signatures
284                .into_iter()
285                .map(|signature| <Signature as AsRef<[u8]>>::as_ref(&signature).into())
286                .collect(),
287            message: Some(value.message.into()),
288        }
289    }
290}
291
292impl From<generated::Transaction> for VersionedTransaction {
293    fn from(value: generated::Transaction) -> Self {
294        Self {
295            signatures: value
296                .signatures
297                .into_iter()
298                .map(Signature::try_from)
299                .collect::<Result<_, _>>()
300                .unwrap(),
301            message: value.message.expect("message is required").into(),
302        }
303    }
304}
305
306impl From<TransactionError> for generated::TransactionError {
307    fn from(value: TransactionError) -> Self {
308        let stored_error = StoredTransactionError::from(value).0;
309        Self { err: stored_error }
310    }
311}
312
313impl From<generated::TransactionError> for TransactionError {
314    fn from(value: generated::TransactionError) -> Self {
315        let stored_error = StoredTransactionError(value.err);
316        stored_error.into()
317    }
318}
319
320impl From<LegacyMessage> for generated::Message {
321    fn from(message: LegacyMessage) -> Self {
322        Self {
323            header: Some(message.header.into()),
324            account_keys: message
325                .account_keys
326                .iter()
327                .map(|key| <Pubkey as AsRef<[u8]>>::as_ref(key).into())
328                .collect(),
329            recent_blockhash: message.recent_blockhash.to_bytes().into(),
330            instructions: message
331                .instructions
332                .into_iter()
333                .map(|ix| ix.into())
334                .collect(),
335            versioned: false,
336            address_table_lookups: vec![],
337            config: None,
338        }
339    }
340}
341
342impl From<v0::Message> for generated::Message {
343    fn from(message: v0::Message) -> Self {
344        Self {
345            header: Some(message.header.into()),
346            account_keys: message
347                .account_keys
348                .iter()
349                .map(|key| <Pubkey as AsRef<[u8]>>::as_ref(key).into())
350                .collect(),
351            recent_blockhash: message.recent_blockhash.to_bytes().into(),
352            instructions: message
353                .instructions
354                .into_iter()
355                .map(|ix| ix.into())
356                .collect(),
357            versioned: true,
358            address_table_lookups: message
359                .address_table_lookups
360                .into_iter()
361                .map(|lookup| lookup.into())
362                .collect(),
363            config: None,
364        }
365    }
366}
367
368impl From<v1::Message> for generated::Message {
369    fn from(message: v1::Message) -> Self {
370        Self {
371            header: Some(message.header.into()),
372            account_keys: message
373                .account_keys
374                .iter()
375                .map(|key| <Pubkey as AsRef<[u8]>>::as_ref(key).into())
376                .collect(),
377            recent_blockhash: message.lifetime_specifier.to_bytes().into(),
378            instructions: message
379                .instructions
380                .into_iter()
381                .map(|ix| ix.into())
382                .collect(),
383            versioned: true,
384            address_table_lookups: vec![],
385            config: Some(generated::TransactionConfig {
386                priority_fee: message.config.priority_fee,
387                compute_unit_limit: message.config.compute_unit_limit,
388                loaded_accounts_data_size_limit: message.config.loaded_accounts_data_size_limit,
389                heap_size: message.config.heap_size,
390            }),
391        }
392    }
393}
394
395impl From<VersionedMessage> for generated::Message {
396    fn from(message: VersionedMessage) -> Self {
397        match message {
398            VersionedMessage::Legacy(message) => Self::from(message),
399            VersionedMessage::V0(message) => Self::from(message),
400            VersionedMessage::V1(message) => Self::from(message),
401        }
402    }
403}
404
405impl From<generated::Message> for VersionedMessage {
406    fn from(value: generated::Message) -> Self {
407        let header = value.header.expect("header is required").into();
408        let account_keys = value
409            .account_keys
410            .into_iter()
411            .map(|key| Pubkey::try_from(key).unwrap())
412            .collect();
413        let recent_blockhash = <[u8; HASH_BYTES]>::try_from(value.recent_blockhash)
414            .map(Hash::new_from_array)
415            .unwrap();
416        let instructions = value.instructions.into_iter().map(|ix| ix.into()).collect();
417        let address_table_lookups = value
418            .address_table_lookups
419            .into_iter()
420            .map(|lookup| lookup.into())
421            .collect();
422
423        if !value.versioned {
424            Self::Legacy(LegacyMessage {
425                header,
426                account_keys,
427                recent_blockhash,
428                instructions,
429            })
430        } else {
431            Self::V0(v0::Message {
432                header,
433                account_keys,
434                recent_blockhash,
435                instructions,
436                address_table_lookups,
437            })
438        }
439    }
440}
441
442impl From<MessageHeader> for generated::MessageHeader {
443    fn from(value: MessageHeader) -> Self {
444        Self {
445            num_required_signatures: value.num_required_signatures as u32,
446            num_readonly_signed_accounts: value.num_readonly_signed_accounts as u32,
447            num_readonly_unsigned_accounts: value.num_readonly_unsigned_accounts as u32,
448        }
449    }
450}
451
452impl From<generated::MessageHeader> for MessageHeader {
453    fn from(value: generated::MessageHeader) -> Self {
454        Self {
455            num_required_signatures: value.num_required_signatures as u8,
456            num_readonly_signed_accounts: value.num_readonly_signed_accounts as u8,
457            num_readonly_unsigned_accounts: value.num_readonly_unsigned_accounts as u8,
458        }
459    }
460}
461
462impl From<TransactionStatusMeta> for generated::TransactionStatusMeta {
463    fn from(value: TransactionStatusMeta) -> Self {
464        let TransactionStatusMeta {
465            status,
466            fee,
467            pre_balances,
468            post_balances,
469            inner_instructions,
470            log_messages,
471            pre_token_balances,
472            post_token_balances,
473            rewards,
474            loaded_addresses,
475            return_data,
476            compute_units_consumed,
477            cost_units,
478        } = value;
479        let err = match status {
480            Ok(()) => None,
481            Err(err) => Some(generated::TransactionError {
482                err: wincode::serialize(&err).expect("transaction error to serialize to bytes"),
483            }),
484        };
485        let inner_instructions_none = inner_instructions.is_none();
486        let inner_instructions = inner_instructions
487            .unwrap_or_default()
488            .into_iter()
489            .map(|ii| ii.into())
490            .collect();
491        let log_messages_none = log_messages.is_none();
492        let log_messages = log_messages.unwrap_or_default();
493        let pre_token_balances = pre_token_balances
494            .unwrap_or_default()
495            .into_iter()
496            .map(|balance| balance.into())
497            .collect();
498        let post_token_balances = post_token_balances
499            .unwrap_or_default()
500            .into_iter()
501            .map(|balance| balance.into())
502            .collect();
503        let rewards = rewards
504            .unwrap_or_default()
505            .into_iter()
506            .map(|reward| reward.into())
507            .collect();
508        let loaded_writable_addresses = loaded_addresses
509            .writable
510            .into_iter()
511            .map(|key| <Pubkey as AsRef<[u8]>>::as_ref(&key).into())
512            .collect();
513        let loaded_readonly_addresses = loaded_addresses
514            .readonly
515            .into_iter()
516            .map(|key| <Pubkey as AsRef<[u8]>>::as_ref(&key).into())
517            .collect();
518        let return_data_none = return_data.is_none();
519        let return_data = return_data.map(|return_data| return_data.into());
520
521        Self {
522            err,
523            fee,
524            pre_balances,
525            post_balances,
526            inner_instructions,
527            inner_instructions_none,
528            log_messages,
529            log_messages_none,
530            pre_token_balances,
531            post_token_balances,
532            rewards,
533            loaded_writable_addresses,
534            loaded_readonly_addresses,
535            return_data,
536            return_data_none,
537            compute_units_consumed,
538            cost_units,
539        }
540    }
541}
542
543impl From<StoredTransactionStatusMeta> for generated::TransactionStatusMeta {
544    fn from(meta: StoredTransactionStatusMeta) -> Self {
545        let meta: TransactionStatusMeta = meta.into();
546        meta.into()
547    }
548}
549
550impl TryFrom<generated::TransactionStatusMeta> for TransactionStatusMeta {
551    type Error = DecodeError;
552
553    fn try_from(value: generated::TransactionStatusMeta) -> std::result::Result<Self, Self::Error> {
554        let generated::TransactionStatusMeta {
555            err,
556            fee,
557            pre_balances,
558            post_balances,
559            inner_instructions,
560            inner_instructions_none,
561            log_messages,
562            log_messages_none,
563            pre_token_balances,
564            post_token_balances,
565            rewards,
566            loaded_writable_addresses,
567            loaded_readonly_addresses,
568            return_data,
569            return_data_none,
570            compute_units_consumed,
571            cost_units,
572        } = value;
573        let status = match err {
574            None => Ok(()),
575            Some(tx_error) => {
576                let tx_error =
577                    wincode::deserialize(&tx_error.err).map_err(|source| DecodeError {
578                        bytes: tx_error.err,
579                        source,
580                    })?;
581                Err(tx_error)
582            }
583        };
584        let inner_instructions = if inner_instructions_none {
585            None
586        } else {
587            Some(
588                inner_instructions
589                    .into_iter()
590                    .map(|inner| inner.into())
591                    .collect(),
592            )
593        };
594        let log_messages = if log_messages_none {
595            None
596        } else {
597            Some(log_messages)
598        };
599        let pre_token_balances = Some(
600            pre_token_balances
601                .into_iter()
602                .map(|balance| balance.into())
603                .collect(),
604        );
605        let post_token_balances = Some(
606            post_token_balances
607                .into_iter()
608                .map(|balance| balance.into())
609                .collect(),
610        );
611        let rewards = Some(rewards.into_iter().map(|reward| reward.into()).collect());
612        let loaded_addresses = LoadedAddresses {
613            writable: loaded_writable_addresses
614                .into_iter()
615                .map(Pubkey::try_from)
616                .collect::<Result<_, _>>()
617                .map_err(|bytes| DecodeError {
618                    bytes,
619                    source: ReadError::Custom("Invalid writable address"),
620                })?,
621            readonly: loaded_readonly_addresses
622                .into_iter()
623                .map(Pubkey::try_from)
624                .collect::<Result<_, _>>()
625                .map_err(|bytes| DecodeError {
626                    bytes,
627                    source: ReadError::Custom("Invalid readonly address"),
628                })?,
629        };
630        let return_data = if return_data_none {
631            None
632        } else {
633            return_data.map(|return_data| return_data.into())
634        };
635        Ok(Self {
636            status,
637            fee,
638            pre_balances,
639            post_balances,
640            inner_instructions,
641            log_messages,
642            pre_token_balances,
643            post_token_balances,
644            rewards,
645            loaded_addresses,
646            return_data,
647            compute_units_consumed,
648            cost_units,
649        })
650    }
651}
652
653impl From<InnerInstructions> for generated::InnerInstructions {
654    fn from(value: InnerInstructions) -> Self {
655        Self {
656            index: value.index as u32,
657            instructions: value.instructions.into_iter().map(|i| i.into()).collect(),
658        }
659    }
660}
661
662impl From<generated::InnerInstructions> for InnerInstructions {
663    fn from(value: generated::InnerInstructions) -> Self {
664        Self {
665            index: value.index as u8,
666            instructions: value.instructions.into_iter().map(|i| i.into()).collect(),
667        }
668    }
669}
670
671impl From<TransactionTokenBalance> for generated::TokenBalance {
672    fn from(value: TransactionTokenBalance) -> Self {
673        Self {
674            account_index: value.account_index as u32,
675            mint: value.mint,
676            ui_token_amount: Some(generated::UiTokenAmount {
677                ui_amount: value.ui_token_amount.ui_amount.unwrap_or_default(),
678                decimals: value.ui_token_amount.decimals as u32,
679                amount: value.ui_token_amount.amount,
680                ui_amount_string: value.ui_token_amount.ui_amount_string,
681            }),
682            owner: value.owner,
683            program_id: value.program_id,
684        }
685    }
686}
687
688impl From<generated::TokenBalance> for TransactionTokenBalance {
689    fn from(value: generated::TokenBalance) -> Self {
690        let ui_token_amount = value.ui_token_amount.unwrap_or_default();
691        Self {
692            account_index: value.account_index as u8,
693            mint: value.mint,
694            ui_token_amount: UiTokenAmount {
695                ui_amount: if (ui_token_amount.ui_amount - f64::default()).abs() > f64::EPSILON {
696                    Some(ui_token_amount.ui_amount)
697                } else {
698                    None
699                },
700                decimals: ui_token_amount.decimals as u8,
701                amount: ui_token_amount.amount.clone(),
702                ui_amount_string: if !ui_token_amount.ui_amount_string.is_empty() {
703                    ui_token_amount.ui_amount_string
704                } else {
705                    real_number_string_trimmed(
706                        u64::from_str(&ui_token_amount.amount).unwrap_or_default(),
707                        ui_token_amount.decimals as u8,
708                    )
709                },
710            },
711            owner: value.owner,
712            program_id: value.program_id,
713        }
714    }
715}
716
717impl From<MessageAddressTableLookup> for generated::MessageAddressTableLookup {
718    fn from(lookup: MessageAddressTableLookup) -> Self {
719        Self {
720            account_key: <Pubkey as AsRef<[u8]>>::as_ref(&lookup.account_key).into(),
721            writable_indexes: lookup.writable_indexes,
722            readonly_indexes: lookup.readonly_indexes,
723        }
724    }
725}
726
727impl From<generated::MessageAddressTableLookup> for MessageAddressTableLookup {
728    fn from(value: generated::MessageAddressTableLookup) -> Self {
729        Self {
730            account_key: Pubkey::try_from(value.account_key).unwrap(),
731            writable_indexes: value.writable_indexes,
732            readonly_indexes: value.readonly_indexes,
733        }
734    }
735}
736
737impl From<TransactionReturnData> for generated::ReturnData {
738    fn from(value: TransactionReturnData) -> Self {
739        Self {
740            program_id: <Pubkey as AsRef<[u8]>>::as_ref(&value.program_id).into(),
741            data: value.data,
742        }
743    }
744}
745
746impl From<generated::ReturnData> for TransactionReturnData {
747    fn from(value: generated::ReturnData) -> Self {
748        Self {
749            program_id: Pubkey::try_from(value.program_id).unwrap(),
750            data: value.data,
751        }
752    }
753}
754
755impl From<CompiledInstruction> for generated::CompiledInstruction {
756    fn from(value: CompiledInstruction) -> Self {
757        Self {
758            program_id_index: value.program_id_index as u32,
759            accounts: value.accounts,
760            data: value.data,
761        }
762    }
763}
764
765impl From<generated::CompiledInstruction> for CompiledInstruction {
766    fn from(value: generated::CompiledInstruction) -> Self {
767        Self {
768            program_id_index: value.program_id_index as u8,
769            accounts: value.accounts,
770            data: value.data,
771        }
772    }
773}
774
775impl From<InnerInstruction> for generated::InnerInstruction {
776    fn from(value: InnerInstruction) -> Self {
777        Self {
778            program_id_index: value.instruction.program_id_index as u32,
779            accounts: value.instruction.accounts,
780            data: value.instruction.data,
781            stack_height: value.stack_height,
782        }
783    }
784}
785
786impl From<generated::InnerInstruction> for InnerInstruction {
787    fn from(value: generated::InnerInstruction) -> Self {
788        Self {
789            instruction: CompiledInstruction {
790                program_id_index: value.program_id_index as u8,
791                accounts: value.accounts,
792                data: value.data,
793            },
794            stack_height: value.stack_height,
795        }
796    }
797}
798
799impl TryFrom<tx_by_addr::TransactionError> for TransactionError {
800    type Error = &'static str;
801
802    fn try_from(transaction_error: tx_by_addr::TransactionError) -> Result<Self, Self::Error> {
803        if transaction_error.transaction_error == 8
804            && let Some(instruction_error) = transaction_error.instruction_error
805        {
806            if let Some(custom) = instruction_error.custom {
807                return Ok(TransactionError::InstructionError(
808                    instruction_error.index as u8,
809                    InstructionError::Custom(custom.custom),
810                ));
811            }
812
813            let ie = match instruction_error.error {
814                0 => InstructionError::GenericError,
815                1 => InstructionError::InvalidArgument,
816                2 => InstructionError::InvalidInstructionData,
817                3 => InstructionError::InvalidAccountData,
818                4 => InstructionError::AccountDataTooSmall,
819                5 => InstructionError::InsufficientFunds,
820                6 => InstructionError::IncorrectProgramId,
821                7 => InstructionError::MissingRequiredSignature,
822                8 => InstructionError::AccountAlreadyInitialized,
823                9 => InstructionError::UninitializedAccount,
824                10 => InstructionError::UnbalancedInstruction,
825                11 => InstructionError::ModifiedProgramId,
826                12 => InstructionError::ExternalAccountLamportSpend,
827                13 => InstructionError::ExternalAccountDataModified,
828                14 => InstructionError::ReadonlyLamportChange,
829                15 => InstructionError::ReadonlyDataModified,
830                16 => InstructionError::DuplicateAccountIndex,
831                17 => InstructionError::ExecutableModified,
832                18 => InstructionError::RentEpochModified,
833                #[allow(deprecated)]
834                19 => InstructionError::NotEnoughAccountKeys,
835                20 => InstructionError::AccountDataSizeChanged,
836                21 => InstructionError::AccountNotExecutable,
837                22 => InstructionError::AccountBorrowFailed,
838                23 => InstructionError::AccountBorrowOutstanding,
839                24 => InstructionError::DuplicateAccountOutOfSync,
840                26 => InstructionError::InvalidError,
841                27 => InstructionError::ExecutableDataModified,
842                28 => InstructionError::ExecutableLamportChange,
843                29 => InstructionError::ExecutableAccountNotRentExempt,
844                30 => InstructionError::UnsupportedProgramId,
845                31 => InstructionError::CallDepth,
846                32 => InstructionError::MissingAccount,
847                33 => InstructionError::ReentrancyNotAllowed,
848                34 => InstructionError::MaxSeedLengthExceeded,
849                35 => InstructionError::InvalidSeeds,
850                36 => InstructionError::InvalidRealloc,
851                37 => InstructionError::ComputationalBudgetExceeded,
852                38 => InstructionError::PrivilegeEscalation,
853                39 => InstructionError::ProgramEnvironmentSetupFailure,
854                40 => InstructionError::ProgramFailedToComplete,
855                41 => InstructionError::ProgramFailedToCompile,
856                42 => InstructionError::Immutable,
857                43 => InstructionError::IncorrectAuthority,
858                44 => InstructionError::BorshIoError,
859                45 => InstructionError::AccountNotRentExempt,
860                46 => InstructionError::InvalidAccountOwner,
861                47 => InstructionError::ArithmeticOverflow,
862                48 => InstructionError::UnsupportedSysvar,
863                49 => InstructionError::IllegalOwner,
864                50 => InstructionError::MaxAccountsDataAllocationsExceeded,
865                51 => InstructionError::MaxAccountsExceeded,
866                52 => InstructionError::MaxInstructionTraceLengthExceeded,
867                53 => InstructionError::BuiltinProgramsMustConsumeComputeUnits,
868                _ => return Err("Invalid InstructionError"),
869            };
870
871            return Ok(TransactionError::InstructionError(
872                instruction_error.index as u8,
873                ie,
874            ));
875        }
876
877        if let Some(transaction_details) = transaction_error.transaction_details {
878            match transaction_error.transaction_error {
879                30 => {
880                    return Ok(TransactionError::DuplicateInstruction(
881                        transaction_details.index as u8,
882                    ));
883                }
884                31 => {
885                    return Ok(TransactionError::InsufficientFundsForRent {
886                        account_index: transaction_details.index as u8,
887                    });
888                }
889
890                35 => {
891                    return Ok(TransactionError::ProgramExecutionTemporarilyRestricted {
892                        account_index: transaction_details.index as u8,
893                    });
894                }
895                _ => {}
896            }
897        }
898
899        Ok(match transaction_error.transaction_error {
900            0 => TransactionError::AccountInUse,
901            1 => TransactionError::AccountLoadedTwice,
902            2 => TransactionError::AccountNotFound,
903            3 => TransactionError::ProgramAccountNotFound,
904            4 => TransactionError::InsufficientFundsForFee,
905            5 => TransactionError::InvalidAccountForFee,
906            6 => TransactionError::AlreadyProcessed,
907            7 => TransactionError::BlockhashNotFound,
908            9 => TransactionError::CallChainTooDeep,
909            10 => TransactionError::MissingSignatureForFee,
910            11 => TransactionError::InvalidAccountIndex,
911            12 => TransactionError::SignatureFailure,
912            13 => TransactionError::InvalidProgramForExecution,
913            14 => TransactionError::SanitizeFailure,
914            15 => TransactionError::ClusterMaintenance,
915            16 => TransactionError::AccountBorrowOutstanding,
916            17 => TransactionError::WouldExceedMaxBlockCostLimit,
917            18 => TransactionError::UnsupportedVersion,
918            19 => TransactionError::InvalidWritableAccount,
919            20 => TransactionError::WouldExceedMaxAccountCostLimit,
920            21 => TransactionError::WouldExceedAccountDataBlockLimit,
921            22 => TransactionError::TooManyAccountLocks,
922            23 => TransactionError::AddressLookupTableNotFound,
923            24 => TransactionError::InvalidAddressLookupTableOwner,
924            25 => TransactionError::InvalidAddressLookupTableData,
925            26 => TransactionError::InvalidAddressLookupTableIndex,
926            27 => TransactionError::InvalidRentPayingAccount,
927            28 => TransactionError::WouldExceedMaxVoteCostLimit,
928            29 => TransactionError::WouldExceedAccountDataTotalLimit,
929            32 => TransactionError::MaxLoadedAccountsDataSizeExceeded,
930            33 => TransactionError::InvalidLoadedAccountsDataSizeLimit,
931            34 => TransactionError::ResanitizationNeeded,
932            36 => TransactionError::UnbalancedTransaction,
933            37 => TransactionError::ProgramCacheHitMaxLimit,
934            38 => TransactionError::CommitCancelled,
935            _ => return Err("Invalid TransactionError"),
936        })
937    }
938}
939
940impl From<TransactionError> for tx_by_addr::TransactionError {
941    fn from(transaction_error: TransactionError) -> Self {
942        Self {
943            transaction_error: match transaction_error {
944                TransactionError::AccountInUse => tx_by_addr::TransactionErrorType::AccountInUse,
945                TransactionError::AccountLoadedTwice => {
946                    tx_by_addr::TransactionErrorType::AccountLoadedTwice
947                }
948                TransactionError::AccountNotFound => {
949                    tx_by_addr::TransactionErrorType::AccountNotFound
950                }
951                TransactionError::ProgramAccountNotFound => {
952                    tx_by_addr::TransactionErrorType::ProgramAccountNotFound
953                }
954                TransactionError::InsufficientFundsForFee => {
955                    tx_by_addr::TransactionErrorType::InsufficientFundsForFee
956                }
957                TransactionError::InvalidAccountForFee => {
958                    tx_by_addr::TransactionErrorType::InvalidAccountForFee
959                }
960                TransactionError::AlreadyProcessed => {
961                    tx_by_addr::TransactionErrorType::AlreadyProcessed
962                }
963                TransactionError::BlockhashNotFound => {
964                    tx_by_addr::TransactionErrorType::BlockhashNotFound
965                }
966                TransactionError::CallChainTooDeep => {
967                    tx_by_addr::TransactionErrorType::CallChainTooDeep
968                }
969                TransactionError::MissingSignatureForFee => {
970                    tx_by_addr::TransactionErrorType::MissingSignatureForFee
971                }
972                TransactionError::InvalidAccountIndex => {
973                    tx_by_addr::TransactionErrorType::InvalidAccountIndex
974                }
975                TransactionError::SignatureFailure => {
976                    tx_by_addr::TransactionErrorType::SignatureFailure
977                }
978                TransactionError::InvalidProgramForExecution => {
979                    tx_by_addr::TransactionErrorType::InvalidProgramForExecution
980                }
981                TransactionError::SanitizeFailure => {
982                    tx_by_addr::TransactionErrorType::SanitizeFailure
983                }
984                TransactionError::ClusterMaintenance => {
985                    tx_by_addr::TransactionErrorType::ClusterMaintenance
986                }
987                TransactionError::InstructionError(_, _) => {
988                    tx_by_addr::TransactionErrorType::InstructionError
989                }
990                TransactionError::AccountBorrowOutstanding => {
991                    tx_by_addr::TransactionErrorType::AccountBorrowOutstandingTx
992                }
993                TransactionError::WouldExceedMaxBlockCostLimit => {
994                    tx_by_addr::TransactionErrorType::WouldExceedMaxBlockCostLimit
995                }
996                TransactionError::UnsupportedVersion => {
997                    tx_by_addr::TransactionErrorType::UnsupportedVersion
998                }
999                TransactionError::InvalidWritableAccount => {
1000                    tx_by_addr::TransactionErrorType::InvalidWritableAccount
1001                }
1002                TransactionError::WouldExceedMaxAccountCostLimit => {
1003                    tx_by_addr::TransactionErrorType::WouldExceedMaxAccountCostLimit
1004                }
1005                TransactionError::WouldExceedAccountDataBlockLimit => {
1006                    tx_by_addr::TransactionErrorType::WouldExceedAccountDataBlockLimit
1007                }
1008                TransactionError::TooManyAccountLocks => {
1009                    tx_by_addr::TransactionErrorType::TooManyAccountLocks
1010                }
1011                TransactionError::AddressLookupTableNotFound => {
1012                    tx_by_addr::TransactionErrorType::AddressLookupTableNotFound
1013                }
1014                TransactionError::InvalidAddressLookupTableOwner => {
1015                    tx_by_addr::TransactionErrorType::InvalidAddressLookupTableOwner
1016                }
1017                TransactionError::InvalidAddressLookupTableData => {
1018                    tx_by_addr::TransactionErrorType::InvalidAddressLookupTableData
1019                }
1020                TransactionError::InvalidAddressLookupTableIndex => {
1021                    tx_by_addr::TransactionErrorType::InvalidAddressLookupTableIndex
1022                }
1023                TransactionError::InvalidRentPayingAccount => {
1024                    tx_by_addr::TransactionErrorType::InvalidRentPayingAccount
1025                }
1026                TransactionError::WouldExceedMaxVoteCostLimit => {
1027                    tx_by_addr::TransactionErrorType::WouldExceedMaxVoteCostLimit
1028                }
1029                TransactionError::WouldExceedAccountDataTotalLimit => {
1030                    tx_by_addr::TransactionErrorType::WouldExceedAccountDataTotalLimit
1031                }
1032                TransactionError::DuplicateInstruction(_) => {
1033                    tx_by_addr::TransactionErrorType::DuplicateInstruction
1034                }
1035                TransactionError::InsufficientFundsForRent { .. } => {
1036                    tx_by_addr::TransactionErrorType::InsufficientFundsForRent
1037                }
1038                TransactionError::MaxLoadedAccountsDataSizeExceeded => {
1039                    tx_by_addr::TransactionErrorType::MaxLoadedAccountsDataSizeExceeded
1040                }
1041                TransactionError::InvalidLoadedAccountsDataSizeLimit => {
1042                    tx_by_addr::TransactionErrorType::InvalidLoadedAccountsDataSizeLimit
1043                }
1044                TransactionError::ResanitizationNeeded => {
1045                    tx_by_addr::TransactionErrorType::ResanitizationNeeded
1046                }
1047                TransactionError::ProgramExecutionTemporarilyRestricted { .. } => {
1048                    tx_by_addr::TransactionErrorType::ProgramExecutionTemporarilyRestricted
1049                }
1050                TransactionError::UnbalancedTransaction => {
1051                    tx_by_addr::TransactionErrorType::UnbalancedTransaction
1052                }
1053                TransactionError::ProgramCacheHitMaxLimit => {
1054                    tx_by_addr::TransactionErrorType::ProgramCacheHitMaxLimit
1055                }
1056                TransactionError::CommitCancelled => {
1057                    tx_by_addr::TransactionErrorType::CommitCancelled
1058                }
1059            } as i32,
1060            instruction_error: match transaction_error {
1061                TransactionError::InstructionError(index, ref instruction_error) => {
1062                    Some(tx_by_addr::InstructionError {
1063                        index: index as u32,
1064                        error: match instruction_error {
1065                            InstructionError::GenericError => {
1066                                tx_by_addr::InstructionErrorType::GenericError
1067                            }
1068                            InstructionError::InvalidArgument => {
1069                                tx_by_addr::InstructionErrorType::InvalidArgument
1070                            }
1071                            InstructionError::InvalidInstructionData => {
1072                                tx_by_addr::InstructionErrorType::InvalidInstructionData
1073                            }
1074                            InstructionError::InvalidAccountData => {
1075                                tx_by_addr::InstructionErrorType::InvalidAccountData
1076                            }
1077                            InstructionError::AccountDataTooSmall => {
1078                                tx_by_addr::InstructionErrorType::AccountDataTooSmall
1079                            }
1080                            InstructionError::InsufficientFunds => {
1081                                tx_by_addr::InstructionErrorType::InsufficientFunds
1082                            }
1083                            InstructionError::IncorrectProgramId => {
1084                                tx_by_addr::InstructionErrorType::IncorrectProgramId
1085                            }
1086                            InstructionError::MissingRequiredSignature => {
1087                                tx_by_addr::InstructionErrorType::MissingRequiredSignature
1088                            }
1089                            InstructionError::AccountAlreadyInitialized => {
1090                                tx_by_addr::InstructionErrorType::AccountAlreadyInitialized
1091                            }
1092                            InstructionError::UninitializedAccount => {
1093                                tx_by_addr::InstructionErrorType::UninitializedAccount
1094                            }
1095                            InstructionError::UnbalancedInstruction => {
1096                                tx_by_addr::InstructionErrorType::UnbalancedInstruction
1097                            }
1098                            InstructionError::ModifiedProgramId => {
1099                                tx_by_addr::InstructionErrorType::ModifiedProgramId
1100                            }
1101                            InstructionError::ExternalAccountLamportSpend => {
1102                                tx_by_addr::InstructionErrorType::ExternalAccountLamportSpend
1103                            }
1104                            InstructionError::ExternalAccountDataModified => {
1105                                tx_by_addr::InstructionErrorType::ExternalAccountDataModified
1106                            }
1107                            InstructionError::ReadonlyLamportChange => {
1108                                tx_by_addr::InstructionErrorType::ReadonlyLamportChange
1109                            }
1110                            InstructionError::ReadonlyDataModified => {
1111                                tx_by_addr::InstructionErrorType::ReadonlyDataModified
1112                            }
1113                            InstructionError::DuplicateAccountIndex => {
1114                                tx_by_addr::InstructionErrorType::DuplicateAccountIndex
1115                            }
1116                            InstructionError::ExecutableModified => {
1117                                tx_by_addr::InstructionErrorType::ExecutableModified
1118                            }
1119                            InstructionError::RentEpochModified => {
1120                                tx_by_addr::InstructionErrorType::RentEpochModified
1121                            }
1122                            #[allow(deprecated)]
1123                            InstructionError::NotEnoughAccountKeys => {
1124                                tx_by_addr::InstructionErrorType::NotEnoughAccountKeys
1125                            }
1126                            InstructionError::AccountDataSizeChanged => {
1127                                tx_by_addr::InstructionErrorType::AccountDataSizeChanged
1128                            }
1129                            InstructionError::AccountNotExecutable => {
1130                                tx_by_addr::InstructionErrorType::AccountNotExecutable
1131                            }
1132                            InstructionError::AccountBorrowFailed => {
1133                                tx_by_addr::InstructionErrorType::AccountBorrowFailed
1134                            }
1135                            InstructionError::AccountBorrowOutstanding => {
1136                                tx_by_addr::InstructionErrorType::AccountBorrowOutstanding
1137                            }
1138                            InstructionError::DuplicateAccountOutOfSync => {
1139                                tx_by_addr::InstructionErrorType::DuplicateAccountOutOfSync
1140                            }
1141                            InstructionError::Custom(_) => tx_by_addr::InstructionErrorType::Custom,
1142                            InstructionError::InvalidError => {
1143                                tx_by_addr::InstructionErrorType::InvalidError
1144                            }
1145                            InstructionError::ExecutableDataModified => {
1146                                tx_by_addr::InstructionErrorType::ExecutableDataModified
1147                            }
1148                            InstructionError::ExecutableLamportChange => {
1149                                tx_by_addr::InstructionErrorType::ExecutableLamportChange
1150                            }
1151                            InstructionError::ExecutableAccountNotRentExempt => {
1152                                tx_by_addr::InstructionErrorType::ExecutableAccountNotRentExempt
1153                            }
1154                            InstructionError::UnsupportedProgramId => {
1155                                tx_by_addr::InstructionErrorType::UnsupportedProgramId
1156                            }
1157                            InstructionError::CallDepth => {
1158                                tx_by_addr::InstructionErrorType::CallDepth
1159                            }
1160                            InstructionError::MissingAccount => {
1161                                tx_by_addr::InstructionErrorType::MissingAccount
1162                            }
1163                            InstructionError::ReentrancyNotAllowed => {
1164                                tx_by_addr::InstructionErrorType::ReentrancyNotAllowed
1165                            }
1166                            InstructionError::MaxSeedLengthExceeded => {
1167                                tx_by_addr::InstructionErrorType::MaxSeedLengthExceeded
1168                            }
1169                            InstructionError::InvalidSeeds => {
1170                                tx_by_addr::InstructionErrorType::InvalidSeeds
1171                            }
1172                            InstructionError::InvalidRealloc => {
1173                                tx_by_addr::InstructionErrorType::InvalidRealloc
1174                            }
1175                            InstructionError::ComputationalBudgetExceeded => {
1176                                tx_by_addr::InstructionErrorType::ComputationalBudgetExceeded
1177                            }
1178                            InstructionError::PrivilegeEscalation => {
1179                                tx_by_addr::InstructionErrorType::PrivilegeEscalation
1180                            }
1181                            InstructionError::ProgramEnvironmentSetupFailure => {
1182                                tx_by_addr::InstructionErrorType::ProgramEnvironmentSetupFailure
1183                            }
1184                            InstructionError::ProgramFailedToComplete => {
1185                                tx_by_addr::InstructionErrorType::ProgramFailedToComplete
1186                            }
1187                            InstructionError::ProgramFailedToCompile => {
1188                                tx_by_addr::InstructionErrorType::ProgramFailedToCompile
1189                            }
1190                            InstructionError::Immutable => {
1191                                tx_by_addr::InstructionErrorType::Immutable
1192                            }
1193                            InstructionError::IncorrectAuthority => {
1194                                tx_by_addr::InstructionErrorType::IncorrectAuthority
1195                            }
1196                            InstructionError::BorshIoError => {
1197                                tx_by_addr::InstructionErrorType::BorshIoError
1198                            }
1199                            InstructionError::AccountNotRentExempt => {
1200                                tx_by_addr::InstructionErrorType::AccountNotRentExempt
1201                            }
1202                            InstructionError::InvalidAccountOwner => {
1203                                tx_by_addr::InstructionErrorType::InvalidAccountOwner
1204                            }
1205                            InstructionError::ArithmeticOverflow => {
1206                                tx_by_addr::InstructionErrorType::ArithmeticOverflow
1207                            }
1208                            InstructionError::UnsupportedSysvar => {
1209                                tx_by_addr::InstructionErrorType::UnsupportedSysvar
1210                            }
1211                            InstructionError::IllegalOwner => {
1212                                tx_by_addr::InstructionErrorType::IllegalOwner
1213                            }
1214                            InstructionError::MaxAccountsDataAllocationsExceeded => {
1215                                tx_by_addr::InstructionErrorType::MaxAccountsDataAllocationsExceeded
1216                            }
1217                            InstructionError::MaxAccountsExceeded => {
1218                                tx_by_addr::InstructionErrorType::MaxAccountsExceeded
1219                            }
1220                            InstructionError::MaxInstructionTraceLengthExceeded => {
1221                                tx_by_addr::InstructionErrorType::MaxInstructionTraceLengthExceeded
1222                            }
1223                            InstructionError::BuiltinProgramsMustConsumeComputeUnits => {
1224                                tx_by_addr::InstructionErrorType::BuiltinProgramsMustConsumeComputeUnits
1225                            }
1226                        } as i32,
1227                        custom: match instruction_error {
1228                            InstructionError::Custom(custom) => {
1229                                Some(tx_by_addr::CustomError { custom: *custom })
1230                            }
1231                            _ => None,
1232                        },
1233                    })
1234                }
1235                _ => None,
1236            },
1237            transaction_details: match transaction_error {
1238                TransactionError::DuplicateInstruction(index) => {
1239                    Some(tx_by_addr::TransactionDetails {
1240                        index: index as u32,
1241                    })
1242                }
1243                TransactionError::InsufficientFundsForRent { account_index } => {
1244                    Some(tx_by_addr::TransactionDetails {
1245                        index: account_index as u32,
1246                    })
1247                }
1248                TransactionError::ProgramExecutionTemporarilyRestricted { account_index } => {
1249                    Some(tx_by_addr::TransactionDetails {
1250                        index: account_index as u32,
1251                    })
1252                }
1253
1254                _ => None,
1255            },
1256        }
1257    }
1258}
1259
1260impl From<TransactionByAddrInfo> for tx_by_addr::TransactionByAddrInfo {
1261    fn from(by_addr: TransactionByAddrInfo) -> Self {
1262        let TransactionByAddrInfo {
1263            signature,
1264            err,
1265            index,
1266            memo,
1267            block_time,
1268        } = by_addr;
1269
1270        Self {
1271            signature: <Signature as AsRef<[u8]>>::as_ref(&signature).into(),
1272            err: err.map(|e| e.into()),
1273            index,
1274            memo: memo.map(|memo| tx_by_addr::Memo { memo }),
1275            block_time: block_time.map(|timestamp| tx_by_addr::UnixTimestamp { timestamp }),
1276        }
1277    }
1278}
1279
1280impl TryFrom<tx_by_addr::TransactionByAddrInfo> for TransactionByAddrInfo {
1281    type Error = &'static str;
1282
1283    fn try_from(
1284        transaction_by_addr: tx_by_addr::TransactionByAddrInfo,
1285    ) -> Result<Self, Self::Error> {
1286        let err = transaction_by_addr
1287            .err
1288            .map(|err| err.try_into())
1289            .transpose()?;
1290
1291        Ok(Self {
1292            signature: Signature::try_from(transaction_by_addr.signature)
1293                .map_err(|_| "Invalid Signature")?,
1294            err,
1295            index: transaction_by_addr.index,
1296            memo: transaction_by_addr
1297                .memo
1298                .map(|tx_by_addr::Memo { memo }| memo),
1299            block_time: transaction_by_addr
1300                .block_time
1301                .map(|tx_by_addr::UnixTimestamp { timestamp }| timestamp),
1302        })
1303    }
1304}
1305
1306impl TryFrom<tx_by_addr::TransactionByAddr> for Vec<TransactionByAddrInfo> {
1307    type Error = &'static str;
1308
1309    fn try_from(collection: tx_by_addr::TransactionByAddr) -> Result<Self, Self::Error> {
1310        collection
1311            .tx_by_addrs
1312            .into_iter()
1313            .map(|tx_by_addr| tx_by_addr.try_into())
1314            .collect::<Result<Vec<TransactionByAddrInfo>, Self::Error>>()
1315    }
1316}
1317
1318impl From<(usize, EntrySummary)> for entries::Entry {
1319    fn from((index, entry_summary): (usize, EntrySummary)) -> Self {
1320        entries::Entry {
1321            index: index as u32,
1322            num_hashes: entry_summary.num_hashes,
1323            hash: entry_summary.hash.as_ref().into(),
1324            num_transactions: entry_summary.num_transactions,
1325            starting_transaction_index: entry_summary.starting_transaction_index as u32,
1326        }
1327    }
1328}
1329
1330impl From<entries::Entry> for EntrySummary {
1331    fn from(entry: entries::Entry) -> Self {
1332        EntrySummary {
1333            num_hashes: entry.num_hashes,
1334            hash: <[u8; HASH_BYTES]>::try_from(entry.hash)
1335                .map(Hash::new_from_array)
1336                .unwrap(),
1337            num_transactions: entry.num_transactions,
1338            starting_transaction_index: entry.starting_transaction_index as usize,
1339        }
1340    }
1341}
1342
1343#[cfg(test)]
1344mod test {
1345    use {super::*, enum_iterator::all};
1346
1347    #[test]
1348    fn test_reward_type_encode() {
1349        let mut reward = Reward {
1350            pubkey: "invalid".to_string(),
1351            lamports: 123,
1352            post_balance: 321,
1353            reward_type: None,
1354            commission: None,
1355            commission_bps: None,
1356        };
1357        let gen_reward: generated::Reward = reward.clone().into();
1358        assert_eq!(reward, gen_reward.into());
1359
1360        reward.reward_type = Some(RewardType::Fee);
1361        let gen_reward: generated::Reward = reward.clone().into();
1362        assert_eq!(reward, gen_reward.into());
1363
1364        reward.reward_type = Some(RewardType::Rent);
1365        let gen_reward: generated::Reward = reward.clone().into();
1366        assert_eq!(reward, gen_reward.into());
1367
1368        reward.reward_type = Some(RewardType::Voting);
1369        let gen_reward: generated::Reward = reward.clone().into();
1370        assert_eq!(reward, gen_reward.into());
1371
1372        reward.reward_type = Some(RewardType::Staking);
1373        let gen_reward: generated::Reward = reward.clone().into();
1374        assert_eq!(reward, gen_reward.into());
1375
1376        reward.reward_type = Some(RewardType::DeactivatedStake);
1377        let gen_reward: generated::Reward = reward.clone().into();
1378        assert_eq!(reward, gen_reward.into());
1379    }
1380
1381    #[test]
1382    fn test_transaction_by_addr_encode() {
1383        let info = TransactionByAddrInfo {
1384            signature: bs58::decode("Nfo6rgemG1KLbk1xuNwfrQTsdxaGfLuWURHNRy9LYnDrubG7LFQZaA5obPNas9LQ6DdorJqxh2LxA3PsnWdkSrL")
1385                .into_vec()
1386                .map(Signature::try_from)
1387                .unwrap()
1388                .unwrap(),
1389            err: None,
1390            index: 5,
1391            memo: Some("string".to_string()),
1392            block_time: Some(1610674861)
1393        };
1394
1395        let tx_by_addr_transaction_info: tx_by_addr::TransactionByAddrInfo = info.clone().into();
1396        assert_eq!(info, tx_by_addr_transaction_info.try_into().unwrap());
1397    }
1398
1399    #[test]
1400    fn test_transaction_error_encode() {
1401        let transaction_error = TransactionError::AccountBorrowOutstanding;
1402        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1403            transaction_error.clone().into();
1404        assert_eq!(
1405            transaction_error,
1406            tx_by_addr_transaction_error.try_into().unwrap()
1407        );
1408
1409        let transaction_error = TransactionError::AccountInUse;
1410        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1411            transaction_error.clone().into();
1412        assert_eq!(
1413            transaction_error,
1414            tx_by_addr_transaction_error.try_into().unwrap()
1415        );
1416
1417        let transaction_error = TransactionError::AccountLoadedTwice;
1418        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1419            transaction_error.clone().into();
1420        assert_eq!(
1421            transaction_error,
1422            tx_by_addr_transaction_error.try_into().unwrap()
1423        );
1424
1425        let transaction_error = TransactionError::AccountNotFound;
1426        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1427            transaction_error.clone().into();
1428        assert_eq!(
1429            transaction_error,
1430            tx_by_addr_transaction_error.try_into().unwrap()
1431        );
1432
1433        let transaction_error = TransactionError::AlreadyProcessed;
1434        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1435            transaction_error.clone().into();
1436        assert_eq!(
1437            transaction_error,
1438            tx_by_addr_transaction_error.try_into().unwrap()
1439        );
1440
1441        let transaction_error = TransactionError::BlockhashNotFound;
1442        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1443            transaction_error.clone().into();
1444        assert_eq!(
1445            transaction_error,
1446            tx_by_addr_transaction_error.try_into().unwrap()
1447        );
1448
1449        let transaction_error = TransactionError::CallChainTooDeep;
1450        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1451            transaction_error.clone().into();
1452        assert_eq!(
1453            transaction_error,
1454            tx_by_addr_transaction_error.try_into().unwrap()
1455        );
1456
1457        let transaction_error = TransactionError::ClusterMaintenance;
1458        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1459            transaction_error.clone().into();
1460        assert_eq!(
1461            transaction_error,
1462            tx_by_addr_transaction_error.try_into().unwrap()
1463        );
1464
1465        let transaction_error = TransactionError::InsufficientFundsForFee;
1466        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1467            transaction_error.clone().into();
1468        assert_eq!(
1469            transaction_error,
1470            tx_by_addr_transaction_error.try_into().unwrap()
1471        );
1472
1473        let transaction_error = TransactionError::InvalidAccountForFee;
1474        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1475            transaction_error.clone().into();
1476        assert_eq!(
1477            transaction_error,
1478            tx_by_addr_transaction_error.try_into().unwrap()
1479        );
1480
1481        let transaction_error = TransactionError::InvalidAccountIndex;
1482        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1483            transaction_error.clone().into();
1484        assert_eq!(
1485            transaction_error,
1486            tx_by_addr_transaction_error.try_into().unwrap()
1487        );
1488
1489        let transaction_error = TransactionError::InvalidProgramForExecution;
1490        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1491            transaction_error.clone().into();
1492        assert_eq!(
1493            transaction_error,
1494            tx_by_addr_transaction_error.try_into().unwrap()
1495        );
1496
1497        let transaction_error = TransactionError::MissingSignatureForFee;
1498        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1499            transaction_error.clone().into();
1500        assert_eq!(
1501            transaction_error,
1502            tx_by_addr_transaction_error.try_into().unwrap()
1503        );
1504
1505        let transaction_error = TransactionError::ProgramAccountNotFound;
1506        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1507            transaction_error.clone().into();
1508        assert_eq!(
1509            transaction_error,
1510            tx_by_addr_transaction_error.try_into().unwrap()
1511        );
1512
1513        let transaction_error = TransactionError::SanitizeFailure;
1514        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1515            transaction_error.clone().into();
1516        assert_eq!(
1517            transaction_error,
1518            tx_by_addr_transaction_error.try_into().unwrap()
1519        );
1520
1521        let transaction_error = TransactionError::SignatureFailure;
1522        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1523            transaction_error.clone().into();
1524        assert_eq!(
1525            transaction_error,
1526            tx_by_addr_transaction_error.try_into().unwrap()
1527        );
1528
1529        let transaction_error = TransactionError::WouldExceedMaxBlockCostLimit;
1530        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1531            transaction_error.clone().into();
1532        assert_eq!(
1533            transaction_error,
1534            tx_by_addr_transaction_error.try_into().unwrap()
1535        );
1536
1537        let transaction_error = TransactionError::WouldExceedMaxVoteCostLimit;
1538        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1539            transaction_error.clone().into();
1540        assert_eq!(
1541            transaction_error,
1542            tx_by_addr_transaction_error.try_into().unwrap()
1543        );
1544
1545        let transaction_error = TransactionError::WouldExceedMaxAccountCostLimit;
1546        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1547            transaction_error.clone().into();
1548        assert_eq!(
1549            transaction_error,
1550            tx_by_addr_transaction_error.try_into().unwrap()
1551        );
1552
1553        let transaction_error = TransactionError::UnsupportedVersion;
1554        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1555            transaction_error.clone().into();
1556        assert_eq!(
1557            transaction_error,
1558            tx_by_addr_transaction_error.try_into().unwrap()
1559        );
1560
1561        let transaction_error =
1562            TransactionError::InstructionError(10, InstructionError::AccountAlreadyInitialized);
1563        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1564            transaction_error.clone().into();
1565        assert_eq!(
1566            transaction_error,
1567            tx_by_addr_transaction_error.try_into().unwrap()
1568        );
1569
1570        let transaction_error =
1571            TransactionError::InstructionError(10, InstructionError::AccountBorrowFailed);
1572        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1573            transaction_error.clone().into();
1574        assert_eq!(
1575            transaction_error,
1576            tx_by_addr_transaction_error.try_into().unwrap()
1577        );
1578
1579        let transaction_error =
1580            TransactionError::InstructionError(10, InstructionError::AccountBorrowOutstanding);
1581        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1582            transaction_error.clone().into();
1583        assert_eq!(
1584            transaction_error,
1585            tx_by_addr_transaction_error.try_into().unwrap()
1586        );
1587
1588        let transaction_error =
1589            TransactionError::InstructionError(10, InstructionError::AccountDataSizeChanged);
1590        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1591            transaction_error.clone().into();
1592        assert_eq!(
1593            transaction_error,
1594            tx_by_addr_transaction_error.try_into().unwrap()
1595        );
1596
1597        let transaction_error =
1598            TransactionError::InstructionError(10, InstructionError::AccountDataTooSmall);
1599        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1600            transaction_error.clone().into();
1601        assert_eq!(
1602            transaction_error,
1603            tx_by_addr_transaction_error.try_into().unwrap()
1604        );
1605
1606        let transaction_error =
1607            TransactionError::InstructionError(10, InstructionError::AccountNotExecutable);
1608        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1609            transaction_error.clone().into();
1610        assert_eq!(
1611            transaction_error,
1612            tx_by_addr_transaction_error.try_into().unwrap()
1613        );
1614
1615        let transaction_error = TransactionError::InstructionError(10, InstructionError::CallDepth);
1616        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1617            transaction_error.clone().into();
1618        assert_eq!(
1619            transaction_error,
1620            tx_by_addr_transaction_error.try_into().unwrap()
1621        );
1622
1623        let transaction_error =
1624            TransactionError::InstructionError(10, InstructionError::ComputationalBudgetExceeded);
1625        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1626            transaction_error.clone().into();
1627        assert_eq!(
1628            transaction_error,
1629            tx_by_addr_transaction_error.try_into().unwrap()
1630        );
1631
1632        let transaction_error =
1633            TransactionError::InstructionError(10, InstructionError::DuplicateAccountIndex);
1634        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1635            transaction_error.clone().into();
1636        assert_eq!(
1637            transaction_error,
1638            tx_by_addr_transaction_error.try_into().unwrap()
1639        );
1640
1641        let transaction_error =
1642            TransactionError::InstructionError(10, InstructionError::DuplicateAccountOutOfSync);
1643        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1644            transaction_error.clone().into();
1645        assert_eq!(
1646            transaction_error,
1647            tx_by_addr_transaction_error.try_into().unwrap()
1648        );
1649
1650        let transaction_error = TransactionError::InstructionError(
1651            10,
1652            InstructionError::ExecutableAccountNotRentExempt,
1653        );
1654        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1655            transaction_error.clone().into();
1656        assert_eq!(
1657            transaction_error,
1658            tx_by_addr_transaction_error.try_into().unwrap()
1659        );
1660
1661        let transaction_error =
1662            TransactionError::InstructionError(10, InstructionError::ExecutableDataModified);
1663        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1664            transaction_error.clone().into();
1665        assert_eq!(
1666            transaction_error,
1667            tx_by_addr_transaction_error.try_into().unwrap()
1668        );
1669
1670        let transaction_error =
1671            TransactionError::InstructionError(10, InstructionError::ExecutableLamportChange);
1672        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1673            transaction_error.clone().into();
1674        assert_eq!(
1675            transaction_error,
1676            tx_by_addr_transaction_error.try_into().unwrap()
1677        );
1678
1679        let transaction_error =
1680            TransactionError::InstructionError(10, InstructionError::ExecutableModified);
1681        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1682            transaction_error.clone().into();
1683        assert_eq!(
1684            transaction_error,
1685            tx_by_addr_transaction_error.try_into().unwrap()
1686        );
1687
1688        let transaction_error =
1689            TransactionError::InstructionError(10, InstructionError::ExternalAccountDataModified);
1690        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1691            transaction_error.clone().into();
1692        assert_eq!(
1693            transaction_error,
1694            tx_by_addr_transaction_error.try_into().unwrap()
1695        );
1696
1697        let transaction_error =
1698            TransactionError::InstructionError(10, InstructionError::ExternalAccountLamportSpend);
1699        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1700            transaction_error.clone().into();
1701        assert_eq!(
1702            transaction_error,
1703            tx_by_addr_transaction_error.try_into().unwrap()
1704        );
1705
1706        let transaction_error =
1707            TransactionError::InstructionError(10, InstructionError::GenericError);
1708        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1709            transaction_error.clone().into();
1710        assert_eq!(
1711            transaction_error,
1712            tx_by_addr_transaction_error.try_into().unwrap()
1713        );
1714
1715        let transaction_error = TransactionError::InstructionError(10, InstructionError::Immutable);
1716        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1717            transaction_error.clone().into();
1718        assert_eq!(
1719            transaction_error,
1720            tx_by_addr_transaction_error.try_into().unwrap()
1721        );
1722
1723        let transaction_error =
1724            TransactionError::InstructionError(10, InstructionError::IncorrectAuthority);
1725        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1726            transaction_error.clone().into();
1727        assert_eq!(
1728            transaction_error,
1729            tx_by_addr_transaction_error.try_into().unwrap()
1730        );
1731
1732        let transaction_error =
1733            TransactionError::InstructionError(10, InstructionError::IncorrectProgramId);
1734        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1735            transaction_error.clone().into();
1736        assert_eq!(
1737            transaction_error,
1738            tx_by_addr_transaction_error.try_into().unwrap()
1739        );
1740
1741        let transaction_error =
1742            TransactionError::InstructionError(10, InstructionError::InsufficientFunds);
1743        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1744            transaction_error.clone().into();
1745        assert_eq!(
1746            transaction_error,
1747            tx_by_addr_transaction_error.try_into().unwrap()
1748        );
1749
1750        let transaction_error =
1751            TransactionError::InstructionError(10, InstructionError::InvalidAccountData);
1752        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1753            transaction_error.clone().into();
1754        assert_eq!(
1755            transaction_error,
1756            tx_by_addr_transaction_error.try_into().unwrap()
1757        );
1758
1759        let transaction_error =
1760            TransactionError::InstructionError(10, InstructionError::InvalidArgument);
1761        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1762            transaction_error.clone().into();
1763        assert_eq!(
1764            transaction_error,
1765            tx_by_addr_transaction_error.try_into().unwrap()
1766        );
1767
1768        let transaction_error =
1769            TransactionError::InstructionError(10, InstructionError::InvalidError);
1770        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1771            transaction_error.clone().into();
1772        assert_eq!(
1773            transaction_error,
1774            tx_by_addr_transaction_error.try_into().unwrap()
1775        );
1776
1777        let transaction_error =
1778            TransactionError::InstructionError(10, InstructionError::InvalidInstructionData);
1779        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1780            transaction_error.clone().into();
1781        assert_eq!(
1782            transaction_error,
1783            tx_by_addr_transaction_error.try_into().unwrap()
1784        );
1785
1786        let transaction_error =
1787            TransactionError::InstructionError(10, InstructionError::InvalidRealloc);
1788        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1789            transaction_error.clone().into();
1790        assert_eq!(
1791            transaction_error,
1792            tx_by_addr_transaction_error.try_into().unwrap()
1793        );
1794
1795        let transaction_error =
1796            TransactionError::InstructionError(10, InstructionError::InvalidSeeds);
1797        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1798            transaction_error.clone().into();
1799        assert_eq!(
1800            transaction_error,
1801            tx_by_addr_transaction_error.try_into().unwrap()
1802        );
1803
1804        let transaction_error =
1805            TransactionError::InstructionError(10, InstructionError::MaxSeedLengthExceeded);
1806        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1807            transaction_error.clone().into();
1808        assert_eq!(
1809            transaction_error,
1810            tx_by_addr_transaction_error.try_into().unwrap()
1811        );
1812
1813        let transaction_error =
1814            TransactionError::InstructionError(10, InstructionError::MissingAccount);
1815        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1816            transaction_error.clone().into();
1817        assert_eq!(
1818            transaction_error,
1819            tx_by_addr_transaction_error.try_into().unwrap()
1820        );
1821
1822        let transaction_error =
1823            TransactionError::InstructionError(10, InstructionError::MissingRequiredSignature);
1824        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1825            transaction_error.clone().into();
1826        assert_eq!(
1827            transaction_error,
1828            tx_by_addr_transaction_error.try_into().unwrap()
1829        );
1830
1831        let transaction_error =
1832            TransactionError::InstructionError(10, InstructionError::ModifiedProgramId);
1833        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1834            transaction_error.clone().into();
1835        assert_eq!(
1836            transaction_error,
1837            tx_by_addr_transaction_error.try_into().unwrap()
1838        );
1839
1840        #[allow(deprecated)]
1841        let transaction_error =
1842            TransactionError::InstructionError(10, InstructionError::NotEnoughAccountKeys);
1843        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1844            transaction_error.clone().into();
1845        assert_eq!(
1846            transaction_error,
1847            tx_by_addr_transaction_error.try_into().unwrap()
1848        );
1849
1850        let transaction_error =
1851            TransactionError::InstructionError(10, InstructionError::PrivilegeEscalation);
1852        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1853            transaction_error.clone().into();
1854        assert_eq!(
1855            transaction_error,
1856            tx_by_addr_transaction_error.try_into().unwrap()
1857        );
1858
1859        let transaction_error = TransactionError::InstructionError(
1860            10,
1861            InstructionError::ProgramEnvironmentSetupFailure,
1862        );
1863        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1864            transaction_error.clone().into();
1865        assert_eq!(
1866            transaction_error,
1867            tx_by_addr_transaction_error.try_into().unwrap()
1868        );
1869
1870        let transaction_error =
1871            TransactionError::InstructionError(10, InstructionError::ProgramFailedToCompile);
1872        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1873            transaction_error.clone().into();
1874        assert_eq!(
1875            transaction_error,
1876            tx_by_addr_transaction_error.try_into().unwrap()
1877        );
1878
1879        let transaction_error =
1880            TransactionError::InstructionError(10, InstructionError::ProgramFailedToComplete);
1881        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1882            transaction_error.clone().into();
1883        assert_eq!(
1884            transaction_error,
1885            tx_by_addr_transaction_error.try_into().unwrap()
1886        );
1887
1888        let transaction_error =
1889            TransactionError::InstructionError(10, InstructionError::ReadonlyDataModified);
1890        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1891            transaction_error.clone().into();
1892        assert_eq!(
1893            transaction_error,
1894            tx_by_addr_transaction_error.try_into().unwrap()
1895        );
1896
1897        let transaction_error =
1898            TransactionError::InstructionError(10, InstructionError::ReadonlyLamportChange);
1899        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1900            transaction_error.clone().into();
1901        assert_eq!(
1902            transaction_error,
1903            tx_by_addr_transaction_error.try_into().unwrap()
1904        );
1905
1906        let transaction_error =
1907            TransactionError::InstructionError(10, InstructionError::ReentrancyNotAllowed);
1908        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1909            transaction_error.clone().into();
1910        assert_eq!(
1911            transaction_error,
1912            tx_by_addr_transaction_error.try_into().unwrap()
1913        );
1914
1915        let transaction_error =
1916            TransactionError::InstructionError(10, InstructionError::RentEpochModified);
1917        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1918            transaction_error.clone().into();
1919        assert_eq!(
1920            transaction_error,
1921            tx_by_addr_transaction_error.try_into().unwrap()
1922        );
1923
1924        let transaction_error =
1925            TransactionError::InstructionError(10, InstructionError::UnbalancedInstruction);
1926        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1927            transaction_error.clone().into();
1928        assert_eq!(
1929            transaction_error,
1930            tx_by_addr_transaction_error.try_into().unwrap()
1931        );
1932
1933        let transaction_error =
1934            TransactionError::InstructionError(10, InstructionError::UninitializedAccount);
1935        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1936            transaction_error.clone().into();
1937        assert_eq!(
1938            transaction_error,
1939            tx_by_addr_transaction_error.try_into().unwrap()
1940        );
1941
1942        let transaction_error =
1943            TransactionError::InstructionError(10, InstructionError::UnsupportedProgramId);
1944        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1945            transaction_error.clone().into();
1946        assert_eq!(
1947            transaction_error,
1948            tx_by_addr_transaction_error.try_into().unwrap()
1949        );
1950
1951        let transaction_error =
1952            TransactionError::InstructionError(10, InstructionError::Custom(10));
1953        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1954            transaction_error.clone().into();
1955        assert_eq!(
1956            transaction_error,
1957            tx_by_addr_transaction_error.try_into().unwrap()
1958        );
1959
1960        let transaction_error = TransactionError::DuplicateInstruction(10);
1961        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1962            transaction_error.clone().into();
1963        assert_eq!(
1964            transaction_error,
1965            tx_by_addr_transaction_error.try_into().unwrap()
1966        );
1967
1968        let transaction_error = TransactionError::InsufficientFundsForRent { account_index: 10 };
1969        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1970            transaction_error.clone().into();
1971        assert_eq!(
1972            transaction_error,
1973            tx_by_addr_transaction_error.try_into().unwrap()
1974        );
1975
1976        let transaction_error = TransactionError::UnbalancedTransaction;
1977        let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1978            transaction_error.clone().into();
1979        assert_eq!(
1980            transaction_error,
1981            tx_by_addr_transaction_error.try_into().unwrap()
1982        );
1983    }
1984
1985    #[test]
1986    fn test_error_enums() {
1987        let ix_index = 1;
1988        let custom_error = 42;
1989        for error in all::<tx_by_addr::TransactionErrorType>() {
1990            match error {
1991                tx_by_addr::TransactionErrorType::DuplicateInstruction
1992                | tx_by_addr::TransactionErrorType::InsufficientFundsForRent
1993                | tx_by_addr::TransactionErrorType::ProgramExecutionTemporarilyRestricted => {
1994                    let tx_by_addr_error = tx_by_addr::TransactionError {
1995                        transaction_error: error as i32,
1996                        instruction_error: None,
1997                        transaction_details: Some(tx_by_addr::TransactionDetails {
1998                            index: ix_index,
1999                        }),
2000                    };
2001                    let transaction_error: TransactionError = tx_by_addr_error
2002                        .try_into()
2003                        .unwrap_or_else(|_| panic!("{error:?} conversion implemented?"));
2004                    assert_eq!(tx_by_addr_error, transaction_error.into());
2005                }
2006                tx_by_addr::TransactionErrorType::InstructionError => {
2007                    for ix_error in all::<tx_by_addr::InstructionErrorType>() {
2008                        if ix_error != tx_by_addr::InstructionErrorType::Custom {
2009                            let tx_by_addr_error = tx_by_addr::TransactionError {
2010                                transaction_error: error as i32,
2011                                instruction_error: Some(tx_by_addr::InstructionError {
2012                                    index: ix_index,
2013                                    error: ix_error as i32,
2014                                    custom: None,
2015                                }),
2016                                transaction_details: None,
2017                            };
2018                            let transaction_error: TransactionError = tx_by_addr_error
2019                                .try_into()
2020                                .unwrap_or_else(|_| panic!("{ix_error:?} conversion implemented?"));
2021                            assert_eq!(tx_by_addr_error, transaction_error.into());
2022                        } else {
2023                            let tx_by_addr_error = tx_by_addr::TransactionError {
2024                                transaction_error: error as i32,
2025                                instruction_error: Some(tx_by_addr::InstructionError {
2026                                    index: ix_index,
2027                                    error: ix_error as i32,
2028                                    custom: Some(tx_by_addr::CustomError {
2029                                        custom: custom_error,
2030                                    }),
2031                                }),
2032                                transaction_details: None,
2033                            };
2034                            let transaction_error: TransactionError =
2035                                tx_by_addr_error.try_into().unwrap();
2036                            assert_eq!(tx_by_addr_error, transaction_error.into());
2037                        }
2038                    }
2039                }
2040                _ => {
2041                    let tx_by_addr_error = tx_by_addr::TransactionError {
2042                        transaction_error: error as i32,
2043                        instruction_error: None,
2044                        transaction_details: None,
2045                    };
2046                    let transaction_error: TransactionError = tx_by_addr_error
2047                        .try_into()
2048                        .unwrap_or_else(|_| panic!("{error:?} conversion implemented?"));
2049                    assert_eq!(tx_by_addr_error, transaction_error.into());
2050                }
2051            }
2052        }
2053    }
2054}