Skip to main content

satellite_bitcoin_transactions/
error.rs

1use arch_program::decode_error::DecodeError;
2use arch_program::program_error::ProgramError;
3use num_derive::FromPrimitive;
4use satellite_collections::generic::fixed_set::FixedSetError;
5use satellite_math::MathError;
6use thiserror::Error;
7
8/// Custom errors for Bitcoin transaction operations.
9///
10/// The first variant starts at 800 to maintain compatibility with the previous
11/// Anchor‐based error numbering.
12#[repr(u32)]
13#[derive(Clone, Copy, Debug, PartialEq, Eq, Error, FromPrimitive)]
14pub enum BitcoinTxError {
15    #[error("Transaction input amount is not enough to cover network fees")]
16    NotEnoughAmountToCoverFees = 800,
17
18    #[error("The resulting transaction exceeds the maximum size allowed")]
19    TransactionTooLarge,
20
21    #[error("An arithmetic error ocurred")]
22    CalcOverflow,
23
24    #[error("The transaction inputs don't cover the amount to be spent in the transaction")]
25    InsufficientInputAmount,
26
27    #[error("The configured fee rate is too low")]
28    InvalidFeeRateTooLow,
29
30    #[error("The utxo was not found in the user utxos")]
31    UtxoNotFoundInUserUtxos,
32
33    #[error("The transaction input length must match the user utxos length")]
34    TransactionInputLengthMustMatchUserUtxosLength,
35
36    #[error("The transaction was not found")]
37    TransactionNotFound,
38
39    #[error("The utxo does not contain runes")]
40    RuneOutputNotFound,
41
42    #[error("The utxo contains more runes than the maximum allowed")]
43    MoreRunesInUtxoThanMax,
44
45    #[error("Not enough BTC in pool")]
46    NotEnoughBtcInPool,
47
48    #[error("The runestone is not valid")]
49    RunestoneDecipherError,
50
51    #[error("Rune input list is full")]
52    RuneInputListFull,
53
54    #[error("Rune addition overflow")]
55    RuneAdditionOverflow,
56
57    #[error("Input to sign list is full")]
58    InputToSignListFull,
59
60    #[error("Modified account list is full")]
61    ModifiedAccountListFull,
62
63    #[error("Failed state transition")]
64    FailedStateTransition,
65
66    #[error("State transitions must be added before any other inputs or outputs")]
67    InvalidStateTransitionOrdering,
68}
69
70// === Conversions ============================================================
71
72impl From<FixedSetError> for BitcoinTxError {
73    fn from(error: FixedSetError) -> Self {
74        match error {
75            FixedSetError::Full => BitcoinTxError::RuneInputListFull,
76            FixedSetError::Duplicate => panic!("Duplicate rune input"),
77        }
78    }
79}
80
81impl From<MathError> for BitcoinTxError {
82    fn from(error: MathError) -> Self {
83        match error {
84            MathError::AdditionOverflow
85            | MathError::SubtractionOverflow
86            | MathError::MultiplicationOverflow
87            | MathError::DivisionOverflow
88            | MathError::ConversionError => BitcoinTxError::CalcOverflow,
89        }
90    }
91}
92
93/// Convert to the generic [`ProgramError`] used by `arch_program`.
94impl From<BitcoinTxError> for ProgramError {
95    fn from(e: BitcoinTxError) -> Self {
96        ProgramError::Custom(e.into())
97    }
98}
99
100/// Allow using `.into()` to convert directly into the underlying `u32` code.
101impl From<BitcoinTxError> for u32 {
102    fn from(e: BitcoinTxError) -> Self {
103        e as u32
104    }
105}
106
107impl DecodeError<BitcoinTxError> for BitcoinTxError {
108    fn type_of() -> &'static str {
109        "BitcoinTxError"
110    }
111}