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}