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