@@ -12,6 +12,9 @@ const DEFAULT_TIMEOUT_SECS: u64 = 30;
1212/// Maximum payload accepted by the Syscoin PoDA endpoint (2 MiB).
1313pub const MAX_BLOB_SIZE : usize = 2 * 1024 * 1024 ;
1414
15+ /// Thread-safe error type
16+ pub type SyscoinError = Box < dyn Error + Send + Sync + ' static > ;
17+
1518/// Response structure for JSON-RPC calls
1619#[ derive( Deserialize , Debug ) ]
1720struct JsonRpcResponse < T > {
@@ -23,13 +26,13 @@ struct JsonRpcResponse<T> {
2326#[ async_trait]
2427pub trait RpcClient {
2528 /// Make a generic RPC call with any method and parameters
26- async fn call ( & self , method : & str , params : & [ Value ] ) -> Result < Value , Box < dyn Error > > ;
29+ async fn call ( & self , method : & str , params : & [ Value ] ) -> Result < Value , SyscoinError > ;
2730
2831 /// Get wallet balance with optional account and watchonly parameters
29- async fn get_balance ( & self , account : Option < & str > , include_watchonly : Option < bool > ) -> Result < f64 , Box < dyn Error > > ;
32+ async fn get_balance ( & self , account : Option < & str > , include_watchonly : Option < bool > ) -> Result < f64 , SyscoinError > ;
3033
3134 /// Make an HTTP GET request to the specified URL
32- async fn http_get ( & self , url : & str ) -> Result < Vec < u8 > , Box < dyn Error > > ;
35+ async fn http_get ( & self , url : & str ) -> Result < Vec < u8 > , SyscoinError > ;
3336}
3437
3538/// Production implementation of the RPC client for Syscoin
@@ -43,7 +46,7 @@ pub struct RealRpcClient {
4346
4447impl RealRpcClient {
4548 /// Create a new RPC client with default timeout
46- pub fn new ( rpc_url : & str , rpc_user : & str , rpc_password : & str , timeout : Option < Duration > ) -> Result < Self , Box < dyn Error > > {
49+ pub fn new ( rpc_url : & str , rpc_user : & str , rpc_password : & str , timeout : Option < Duration > ) -> Result < Self , SyscoinError > {
4750 Self :: new_with_timeout ( rpc_url, rpc_user, rpc_password, timeout)
4851 }
4952
@@ -53,7 +56,7 @@ impl RealRpcClient {
5356 rpc_user : & str ,
5457 rpc_password : & str ,
5558 timeout : Option < Duration > ,
56- ) -> Result < Self , Box < dyn Error > > {
59+ ) -> Result < Self , SyscoinError > {
5760 let timeout = timeout. unwrap_or_else ( || Duration :: from_secs ( DEFAULT_TIMEOUT_SECS ) ) ;
5861
5962 let http_client = ClientBuilder :: new ( )
@@ -70,7 +73,7 @@ impl RealRpcClient {
7073 }
7174
7275 /// Send a JSON-RPC request to the Syscoin node
73- async fn rpc_request ( & self , method : & str , params : & [ Value ] ) -> Result < Value , Box < dyn Error > > {
76+ async fn rpc_request ( & self , method : & str , params : & [ Value ] ) -> Result < Value , SyscoinError > {
7477 let request_body = json ! ( {
7578 "jsonrpc" : "2.0" ,
7679 "id" : 1 ,
@@ -100,7 +103,7 @@ impl RealRpcClient {
100103 }
101104
102105 /// Create or load a wallet by name
103- pub async fn create_or_load_wallet ( & self , wallet_name : & str ) -> Result < ( ) , Box < dyn Error > > {
106+ pub async fn create_or_load_wallet ( & self , wallet_name : & str ) -> Result < ( ) , SyscoinError > {
104107 // First try to load the wallet
105108 match self . call ( "loadwallet" , & [ json ! ( wallet_name) ] ) . await {
106109 Ok ( _) => return Ok ( ( ) ) ,
@@ -115,11 +118,11 @@ impl RealRpcClient {
115118
116119#[ async_trait]
117120impl RpcClient for RealRpcClient {
118- async fn call ( & self , method : & str , params : & [ Value ] ) -> Result < Value , Box < dyn Error > > {
121+ async fn call ( & self , method : & str , params : & [ Value ] ) -> Result < Value , SyscoinError > {
119122 self . rpc_request ( method, params) . await
120123 }
121124
122- async fn get_balance ( & self , account : Option < & str > , include_watchonly : Option < bool > ) -> Result < f64 , Box < dyn Error > > {
125+ async fn get_balance ( & self , account : Option < & str > , include_watchonly : Option < bool > ) -> Result < f64 , SyscoinError > {
123126 let mut params = Vec :: new ( ) ;
124127
125128 if let Some ( acct) = account {
@@ -136,7 +139,7 @@ impl RpcClient for RealRpcClient {
136139 Ok ( balance)
137140 }
138141
139- async fn http_get ( & self , url : & str ) -> Result < Vec < u8 > , Box < dyn Error > > {
142+ async fn http_get ( & self , url : & str ) -> Result < Vec < u8 > , SyscoinError > {
140143 let response = self . http_client . get ( url) . send ( ) . await ?;
141144
142145 if !response. status ( ) . is_success ( ) {
@@ -160,7 +163,7 @@ impl SyscoinClient {
160163 rpc_password : & str ,
161164 poda_url : & str ,
162165 timeout : Option < Duration > ,
163- ) -> Result < Self , Box < dyn Error > > {
166+ ) -> Result < Self , SyscoinError > {
164167 let rpc_client = RealRpcClient :: new_with_timeout ( rpc_url, rpc_user, rpc_password, timeout) ?;
165168
166169 Ok ( Self {
@@ -169,8 +172,13 @@ impl SyscoinClient {
169172 } )
170173 }
171174
175+ /// Return the maximum supported blob size
176+ pub fn max_blob_size ( & self ) -> usize {
177+ MAX_BLOB_SIZE
178+ }
179+
172180 /// Create a blob in BitcoinDA(FKA Poda) storage
173- pub async fn create_blob ( & self , data : & [ u8 ] ) -> Result < String , Box < dyn Error > > {
181+ pub async fn create_blob ( & self , data : & [ u8 ] ) -> Result < String , SyscoinError > {
174182 if data. len ( ) > MAX_BLOB_SIZE {
175183 return Err ( format ! (
176184 "blob size ({}) exceeds maximum allowed ({})" ,
@@ -193,12 +201,12 @@ impl SyscoinClient {
193201 }
194202
195203 /// Get wallet balance
196- pub async fn get_balance ( & self ) -> Result < f64 , Box < dyn Error > > {
204+ pub async fn get_balance ( & self ) -> Result < f64 , SyscoinError > {
197205 self . rpc_client . get_balance ( None , None ) . await
198206 }
199207
200208 /// Fetch a blob; tries RPC first, then falls back to PoDA cloud
201- pub async fn get_blob ( & self , blob_id : & str ) -> Result < Vec < u8 > , Box < dyn Error > > {
209+ pub async fn get_blob ( & self , blob_id : & str ) -> Result < Vec < u8 > , SyscoinError > {
202210 match self . get_blob_from_rpc ( blob_id) . await {
203211 Ok ( data) => Ok ( data) ,
204212 Err ( e) => {
@@ -209,7 +217,7 @@ impl SyscoinClient {
209217 }
210218
211219 /// Retrieve blob data from RPC node
212- async fn get_blob_from_rpc ( & self , blob_id : & str ) -> Result < Vec < u8 > , Box < dyn Error > > {
220+ async fn get_blob_from_rpc ( & self , blob_id : & str ) -> Result < Vec < u8 > , SyscoinError > {
213221 // Strip any 0x prefix
214222 let actual_blob_id = if let Some ( stripped) = blob_id. strip_prefix ( "0x" ) {
215223 stripped
@@ -241,20 +249,15 @@ impl SyscoinClient {
241249 }
242250
243251 /// Retrieve blob data from PODA cloud storage
244- pub async fn get_blob_from_cloud ( & self , version_hash : & str ) -> Result < Vec < u8 > , Box < dyn Error > > {
252+ pub async fn get_blob_from_cloud ( & self , version_hash : & str ) -> Result < Vec < u8 > , SyscoinError > {
245253 let url = format ! ( "{}/blob/{}" , self . poda_url, version_hash) ;
246254 self . rpc_client . http_get ( & url) . await
247255 }
248256
249257 /// Create or load a wallet by name
250- pub async fn create_or_load_wallet ( & self , wallet_name : & str ) -> Result < ( ) , Box < dyn Error > > {
258+ pub async fn create_or_load_wallet ( & self , wallet_name : & str ) -> Result < ( ) , SyscoinError > {
251259 self . rpc_client . create_or_load_wallet ( wallet_name) . await
252260 }
253-
254- /// Return the maximum supported blob size
255- pub fn max_blob_size ( & self ) -> usize {
256- MAX_BLOB_SIZE
257- }
258261}
259262
260263/// Mock implementation for testing
@@ -266,7 +269,7 @@ pub struct MockRpcClient {
266269#[ cfg( test) ]
267270#[ async_trait]
268271impl RpcClient for MockRpcClient {
269- async fn call ( & self , method : & str , _params : & [ Value ] ) -> Result < Value , Box < dyn Error > > {
272+ async fn call ( & self , method : & str , _params : & [ Value ] ) -> Result < Value , SyscoinError > {
270273 // Return mock responses based on the method
271274 match method {
272275 "getbalance" => Ok ( json ! ( 10.5 ) ) ,
@@ -278,11 +281,11 @@ impl RpcClient for MockRpcClient {
278281 }
279282 }
280283
281- async fn get_balance ( & self , _account : Option < & str > , _include_watchonly : Option < bool > ) -> Result < f64 , Box < dyn Error > > {
284+ async fn get_balance ( & self , _account : Option < & str > , _include_watchonly : Option < bool > ) -> Result < f64 , SyscoinError > {
282285 Ok ( 10.5 )
283286 }
284287
285- async fn http_get ( & self , _url : & str ) -> Result < Vec < u8 > , Box < dyn Error > > {
288+ async fn http_get ( & self , _url : & str ) -> Result < Vec < u8 > , SyscoinError > {
286289 Ok ( b"mock_data" . to_vec ( ) )
287290 }
288291}
0 commit comments