tx3_resolver/trp/
errors.rs1use serde_json::json;
2use tx3_tir::encoding;
3
4use crate::{inputs::CanonicalQuery, trp::spec, Error};
5
6pub const CODE_UNSUPPORTED_TIR: i32 = -32000;
7pub const CODE_MISSING_TX_ARG: i32 = -32001;
8pub const CODE_INPUT_NOT_RESOLVED: i32 = -32002;
9pub const CODE_TX_SCRIPT_FAILURE: i32 = -32003;
10pub const CODE_TX_NOT_ACCEPTED: i32 = -32004;
11pub const CODE_INTEROP_ERROR: i32 = -32005;
12pub const CODE_COMPILE_ERROR: i32 = -32006;
13pub const CODE_INPUT_QUERY_TOO_BROAD: i32 = -32007;
14pub const CODE_UTXO_STORE_ERROR: i32 = -32008;
15pub const CODE_TRANSIENT_ERROR: i32 = -32009;
16
17pub trait TrpError {
23 fn code(&self) -> i32;
24 fn data(&self) -> Option<serde_json::Value>;
25}
26
27pub trait IntoErrorData {
28 type Output;
29 fn into_error_data(self) -> Self::Output;
30}
31
32impl IntoErrorData for CanonicalQuery {
33 type Output = spec::InputQueryDiagnostic;
34
35 fn into_error_data(self) -> Self::Output {
36 spec::InputQueryDiagnostic {
37 address: self.address.as_ref().map(hex::encode),
38 min_amount: self
39 .min_amount
40 .iter()
41 .flat_map(|x| x.iter())
42 .map(|(k, v)| (k.to_string(), v.to_string()))
43 .collect(),
44 refs: self
45 .refs
46 .iter()
47 .map(ToString::to_string)
48 .collect::<Vec<_>>(),
49 support_many: self.support_many,
50 collateral: self.collateral,
51 }
52 }
53}
54
55impl TrpError for encoding::Error {
56 fn code(&self) -> i32 {
57 match self {
58 encoding::Error::DeprecatedTirVersion(_) => CODE_UNSUPPORTED_TIR,
59 encoding::Error::UnknownTirVersion(_) => CODE_UNSUPPORTED_TIR,
60 encoding::Error::TirDeserializeError(_) => CODE_UNSUPPORTED_TIR,
61 }
62 }
63
64 fn data(&self) -> Option<serde_json::Value> {
65 match self {
66 encoding::Error::DeprecatedTirVersion(version) => {
67 let data = spec::UnsupportedTirDiagnostic {
68 provided: version.to_string(),
69 expected: tx3_tir::encoding::MIN_SUPPORTED_VERSION.to_string(),
70 };
71
72 Some(json!(data))
73 }
74 encoding::Error::UnknownTirVersion(version) => {
75 let data = spec::UnsupportedTirDiagnostic {
76 provided: version.to_string(),
77 expected: tx3_tir::encoding::MIN_SUPPORTED_VERSION.to_string(),
78 };
79
80 Some(json!(data))
81 }
82 encoding::Error::TirDeserializeError(_) => None,
83 }
84 }
85}
86
87impl TrpError for crate::Error {
88 fn code(&self) -> i32 {
89 match self {
90 Error::InputQueryTooBroad => CODE_INPUT_QUERY_TOO_BROAD,
91 Error::InputNotResolved(..) => CODE_INPUT_NOT_RESOLVED,
92 Error::MissingTxArg { .. } => CODE_MISSING_TX_ARG,
93 Error::CompileError(..) => CODE_COMPILE_ERROR,
94 Error::CantCompileNonConstantTir => CODE_COMPILE_ERROR,
95 Error::ExpectedData(..) => CODE_COMPILE_ERROR,
96 Error::TransientError(_) => CODE_TRANSIENT_ERROR,
97 Error::StoreError(_) => CODE_UTXO_STORE_ERROR,
98 Error::InteropError(_) => CODE_INTEROP_ERROR,
99 Error::ReduceError(_) => CODE_COMPILE_ERROR,
100 Error::TxScriptFailure(_) => CODE_TX_SCRIPT_FAILURE,
101 Error::TxNotAccepted(_) => CODE_TX_NOT_ACCEPTED,
102 Error::TirEncodingError(x) => x.code(),
103 }
104 }
105
106 fn data(&self) -> Option<serde_json::Value> {
107 match self {
108 Error::TirEncodingError(x) => x.data(),
109
110 Error::MissingTxArg { key, ty } => {
111 let data = spec::MissingTxArgDiagnostic {
112 key: key.to_string(),
113 ty: format!("{ty:?}"),
114 };
115
116 Some(json!(data))
117 }
118 Error::InputNotResolved(name, q, pool) => {
119 let data = spec::InputNotResolvedDiagnostic {
120 name: name.to_string(),
121 query: q.clone().into_error_data(),
122 search_space: spec::SearchSpaceDiagnostic {
123 matched: pool.iter().map(ToString::to_string).collect(),
124 by_address_count: None,
125 by_asset_class_count: None,
126 by_ref_count: None,
127 },
128 };
129
130 Some(json!(data))
131 }
132
133 Error::TxScriptFailure(x) => {
134 let data = spec::TxScriptFailureDiagnostic { logs: x.clone() };
135 Some(json!(data))
136 }
137 _ => None,
138 }
139 }
140}