oasis_types/
lib.rs

1#![feature(non_exhaustive)]
2
3#[macro_use]
4extern crate derive_more;
5
6mod address;
7mod balance;
8
9pub use address::Address;
10pub use balance::Balance;
11
12#[derive(PartialEq, Eq, Debug)]
13#[repr(u32)]
14#[non_exhaustive]
15#[doc(hidden)]
16pub enum ExtStatusCode {
17    Success,
18    InsufficientFunds,
19    InvalidInput,
20    NoAccount,
21}
22
23#[derive(Clone, Default, Debug, PartialEq, Eq)]
24pub struct AccountMeta {
25    pub balance: u128,
26    pub expiry: Option<std::time::Duration>,
27}
28
29#[derive(Clone, Default, Debug, PartialEq, Eq)]
30pub struct Event {
31    pub emitter: Address,
32    pub topics: Vec<[u8; 32]>,
33    pub data: Vec<u8>,
34}
35
36#[derive(Debug, thiserror::Error)]
37#[cfg_attr(target_os = "wasi", derive(Clone))]
38pub enum RpcError {
39    /// There was no service at the requested address.
40    #[error("invalid callee")]
41    InvalidCallee,
42
43    /// The caller does not have enough balance to cover the sent value.
44    #[error("caller does not have enough balance to cover transaction")]
45    InsufficientFunds,
46
47    /// The caller did not provide enough gas to complete the transaction.
48    #[error("not enough gas provided to transaction")]
49    InsufficientGas,
50
51    #[error("transaction received invalid input")]
52    InvalidInput,
53
54    #[error("transaction returned invalid output")]
55    InvalidOutput(Vec<u8>),
56
57    /// The application returned an error.
58    #[error("an application error occurred")]
59    Execution(Vec<u8>),
60
61    /// The gateway client encountered an error.
62    #[cfg(not(target_os = "wasi"))]
63    #[error("gateway error: {0}")]
64    Gateway(#[source] anyhow::Error),
65}
66
67const _IMPL_SERDE_FOR_RPC_ERROR: () = {
68    impl oasis_borsh::ser::BorshSerialize for RpcError {
69        fn serialize<W: std::io::Write>(
70            &self,
71            writer: &mut W,
72        ) -> std::result::Result<(), std::io::Error> {
73            match self {
74                RpcError::InvalidCallee => {
75                    let variant_idx = 0u8;
76                    writer.write_all(&variant_idx.to_le_bytes())?;
77                }
78                RpcError::InsufficientFunds => {
79                    let variant_idx = 1u8;
80                    writer.write_all(&variant_idx.to_le_bytes())?;
81                }
82                RpcError::InsufficientGas => {
83                    let variant_idx = 2u8;
84                    writer.write_all(&variant_idx.to_le_bytes())?;
85                }
86                RpcError::InvalidInput => {
87                    let variant_idx = 3u8;
88                    writer.write_all(&variant_idx.to_le_bytes())?;
89                }
90                RpcError::InvalidOutput(output) => {
91                    let variant_idx = 4u8;
92                    writer.write_all(&variant_idx.to_le_bytes())?;
93                    oasis_borsh::BorshSerialize::serialize(output, writer)?;
94                }
95                RpcError::Execution(output) => {
96                    let variant_idx = 5u8;
97                    writer.write_all(&variant_idx.to_le_bytes())?;
98                    oasis_borsh::BorshSerialize::serialize(output, writer)?;
99                }
100                #[cfg(not(target_os = "wasi"))]
101                RpcError::Gateway(e) => {
102                    let variant_idx = 6u8;
103                    writer.write_all(&variant_idx.to_le_bytes())?;
104                    oasis_borsh::BorshSerialize::serialize(&e.to_string(), writer)?;
105                }
106            }
107            Ok(())
108        }
109    }
110
111    impl oasis_borsh::de::BorshDeserialize for RpcError {
112        fn deserialize<R: std::io::Read>(
113            reader: &mut R,
114        ) -> std::result::Result<Self, std::io::Error> {
115            let mut variant_idx = [0u8];
116            reader.read_exact(&mut variant_idx)?;
117            let variant_idx = variant_idx[0];
118            let return_value = match variant_idx {
119                0u8 => RpcError::InvalidCallee,
120                1u8 => RpcError::InsufficientFunds,
121                2u8 => RpcError::InsufficientGas,
122                3u8 => RpcError::InvalidInput,
123                4u8 => RpcError::InvalidOutput(oasis_borsh::BorshDeserialize::deserialize(reader)?),
124                5u8 => RpcError::Execution(oasis_borsh::BorshDeserialize::deserialize(reader)?),
125                #[cfg(not(target_os = "wasi"))]
126                6u8 => {
127                    let err_str: String = oasis_borsh::BorshDeserialize::deserialize(reader)?;
128                    RpcError::Gateway(anyhow::anyhow!(err_str))
129                }
130                _ => {
131                    return Err(std::io::Error::new(
132                        std::io::ErrorKind::InvalidInput,
133                        format!("Unexpected variant index: {}", variant_idx),
134                    ))
135                }
136            };
137            Ok(return_value)
138        }
139    }
140};
141
142impl RpcError {
143    pub fn execution(&self) -> Option<&[u8]> {
144        match self {
145            RpcError::Execution(output) => Some(&output),
146            _ => None,
147        }
148    }
149}