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 #[error("invalid callee")]
41 InvalidCallee,
42
43 #[error("caller does not have enough balance to cover transaction")]
45 InsufficientFunds,
46
47 #[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 #[error("an application error occurred")]
59 Execution(Vec<u8>),
60
61 #[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}