solana_storage_proto/
convert.rs

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