1
1
use clap:: ArgMatches ;
2
- use failure:: Fail ;
3
2
use http;
4
3
use reqwest:: { self , Client , Response } ;
5
4
use std:: { borrow:: Cow , collections:: HashMap } ;
6
5
use tungstenite:: { connect, handshake:: client:: Request } ;
7
6
use url:: Url ;
8
7
9
- #[ derive( Debug , Fail ) ]
8
+ #[ derive( Debug , thiserror :: Error ) ]
10
9
pub enum Error {
11
- #[ fail( display = "Usage error" ) ]
10
+ // Custom errors
11
+ #[ error( "Usage error" ) ]
12
12
UsageErr ( & ' static str ) ,
13
- #[ fail( display = "Error sending request: {}" , _0) ]
14
- ClientErr ( reqwest:: Error ) ,
15
- #[ fail( display = "Error receiving response: {}" , _0) ]
16
- ResponseErr ( String ) ,
17
- #[ fail( display = "Error parsing URL protocol: {}" , _0) ]
18
- ProtocolErr ( & ' static str ) ,
19
- #[ fail( display = "Error altering URL scheme" ) ]
20
- SchemeErr ( ) ,
21
- #[ fail( display = "Error parsing URL: {}" , _0) ]
22
- UrlErr ( url:: ParseError ) ,
23
- #[ fail( display = "Error connecting to WebSocket host: {}" , _0) ]
24
- WebsocketErr ( tungstenite:: error:: Error ) ,
25
- }
26
-
27
- impl From < url:: ParseError > for Error {
28
- fn from ( error : url:: ParseError ) -> Self {
29
- Error :: UrlErr ( error)
30
- }
31
- }
32
-
33
- impl From < tungstenite:: error:: Error > for Error {
34
- fn from ( error : tungstenite:: error:: Error ) -> Self {
35
- Error :: WebsocketErr ( error)
36
- }
13
+ #[ error( "Invalid protocol in URL: {0}" ) ]
14
+ ProtocolErr ( String ) ,
15
+ // Foreign errors
16
+ #[ error( "Error sending HTTP request: {0}" ) ]
17
+ ClientErr ( #[ from] reqwest:: Error ) ,
18
+ #[ error( "Error altering URL scheme" ) ]
19
+ SchemeErr ( ( ) ) , // TODO: should be part of UrlError, see https://github.com/servo/rust-url/issues/299
20
+ #[ error( "Error parsing URL: {0}" ) ]
21
+ UrlErr ( #[ from] url:: ParseError ) ,
22
+ #[ error( "WebSocket error: {0}" ) ]
23
+ WebsocketErr ( #[ from] tungstenite:: error:: Error ) ,
37
24
}
38
25
39
26
pub fn run ( matches : & ArgMatches ) -> Result < Response , Error > {
40
27
let client = NodeClient {
41
28
client : Client :: new ( ) ,
42
- // `--node` has a a default value, so will never be None
43
- url : matches. value_of ( "node_url" ) . unwrap ( ) ,
29
+ url : matches. value_of ( "node_url" ) . unwrap ( ) , // infallible unwrap
44
30
} ;
45
31
46
32
// Dispatch based on parsed input
@@ -92,7 +78,7 @@ impl NodeClient<'_> {
92
78
// GET /accounts/:username/balance
93
79
fn get_account_balance ( & self , matches : & ArgMatches ) -> Result < Response , Error > {
94
80
let ( auth, mut args) = extract_args ( matches) ;
95
- let user = args. remove ( "username" ) . unwrap ( ) ;
81
+ let user = args. remove ( "username" ) . unwrap ( ) ; // infallible unwrap
96
82
self . client
97
83
. get ( & format ! ( "{}/accounts/{}/balance" , self . url, user) )
98
84
. bearer_auth ( auth)
@@ -143,12 +129,13 @@ impl NodeClient<'_> {
143
129
let scheme = match url. scheme ( ) {
144
130
"http" => Ok ( "ws" ) ,
145
131
"https" => Ok ( "wss" ) ,
146
- _ => Err ( Error :: ProtocolErr ( "Unexpected protocol" ) ) ,
132
+ s => Err ( Error :: ProtocolErr ( format ! (
133
+ "{} (only HTTP and HTTPS are supported)" ,
134
+ s
135
+ ) ) ) ,
147
136
} ?;
148
137
149
- if url. set_scheme ( scheme) . is_err ( ) {
150
- return Err ( Error :: SchemeErr ( ) ) ;
151
- } ;
138
+ url. set_scheme ( scheme) . map_err ( Error :: SchemeErr ) ?;
152
139
153
140
let mut request: Request = url. into ( ) ;
154
141
request. add_header (
@@ -158,9 +145,7 @@ impl NodeClient<'_> {
158
145
159
146
let ( mut socket, _) = connect ( request) ?;
160
147
loop {
161
- let msg = socket
162
- . read_message ( )
163
- . expect ( "Could not receive WebSocket message" ) ;
148
+ let msg = socket. read_message ( ) ?;
164
149
println ! ( "{}" , msg) ;
165
150
}
166
151
}
@@ -188,7 +173,7 @@ impl NodeClient<'_> {
188
173
// PUT /accounts/:username/settings
189
174
fn put_account_settings ( & self , matches : & ArgMatches ) -> Result < Response , Error > {
190
175
let ( auth, mut args) = extract_args ( matches) ;
191
- let user = args. remove ( "username" ) . unwrap ( ) ;
176
+ let user = args. remove ( "username" ) . unwrap ( ) ; // infallible unwrap
192
177
self . client
193
178
. put ( & format ! ( "{}/accounts/{}/settings" , self . url, user) )
194
179
. bearer_auth ( auth)
@@ -200,7 +185,7 @@ impl NodeClient<'_> {
200
185
// POST /accounts/:username/payments
201
186
fn post_account_payments ( & self , matches : & ArgMatches ) -> Result < Response , Error > {
202
187
let ( auth, mut args) = extract_args ( matches) ;
203
- let user = args. remove ( "sender_username" ) . unwrap ( ) ;
188
+ let user = args. remove ( "sender_username" ) . unwrap ( ) ; // infallible unwrap
204
189
self . client
205
190
. post ( & format ! ( "{}/accounts/{}/payments" , self . url, user) )
206
191
. bearer_auth ( & format ! ( "{}:{}" , user, auth) )
@@ -276,6 +261,7 @@ impl NodeClient<'_> {
276
261
. send ( )
277
262
. map_err ( Error :: ClientErr )
278
263
}
264
+
279
265
/*
280
266
{"http_endpoint": "https://rs3.xpring.dev/ilp", // ilp_over_http_url
281
267
"passkey": "b0i3q9tbvfgek", // ilp_over_http_outgoing_token = username:passkey
@@ -287,7 +273,6 @@ impl NodeClient<'_> {
287
273
"payment_pointer": "$rs3.xpring.dev/accounts/user_g31tuju4/spsp"}
288
274
routing_relation Parent
289
275
*/
290
-
291
276
fn xpring_account ( & self , matches : & ArgMatches ) -> Result < Response , Error > {
292
277
let ( auth, cli_args) = extract_args ( matches) ;
293
278
// Note the Xpring API expects the asset code in lowercase
@@ -296,31 +281,17 @@ impl NodeClient<'_> {
296
281
. client
297
282
. get ( & format ! ( "https://xpring.io/api/accounts/{}" , asset) )
298
283
. send ( )
299
- . map_err ( |err| {
300
- Error :: ResponseErr ( format ! (
301
- "Error requesting credentials from Xpring Testnet Signup API: {:?}" ,
302
- err
303
- ) )
304
- } ) ?
284
+ . map_err ( Error :: ClientErr ) ?
305
285
. json ( )
306
- . map_err ( |err| {
307
- Error :: ResponseErr ( format ! (
308
- "Got unexpected response from Xpring Testnet Signup API: {:?}" ,
309
- err
310
- ) )
311
- } ) ?;
286
+ . map_err ( Error :: ClientErr ) ?;
312
287
let mut args = HashMap :: new ( ) ;
313
- let token = format ! (
314
- "{}:{}" ,
315
- foreign_args. username. clone( ) ,
316
- foreign_args. passkey. clone( )
317
- ) ;
318
- args. insert ( "ilp_over_http_url" , foreign_args. http_endpoint . clone ( ) ) ;
288
+ let token = format ! ( "{}:{}" , foreign_args. username, foreign_args. passkey) ;
289
+ args. insert ( "ilp_over_http_url" , foreign_args. http_endpoint ) ;
319
290
args. insert ( "ilp_over_http_outgoing_token" , token. clone ( ) ) ;
320
- args. insert ( "ilp_over_btp_url" , foreign_args. btp_endpoint . clone ( ) ) ;
291
+ args. insert ( "ilp_over_btp_url" , foreign_args. btp_endpoint ) ;
321
292
args. insert ( "ilp_over_btp_outgoing_token" , token. clone ( ) ) ;
322
293
args. insert ( "asset_scale" , foreign_args. asset_scale . to_string ( ) ) ;
323
- args. insert ( "asset_code" , foreign_args. asset_code . clone ( ) ) ;
294
+ args. insert ( "asset_code" , foreign_args. asset_code ) ;
324
295
args. insert ( "username" , format ! ( "xpring_{}" , asset) ) ;
325
296
args. insert ( "routing_relation" , String :: from ( "Parent" ) ) ; // TODO: weird behavior when deleting and re-inserting accounts with this
326
297
// TODO should we set different parameters?
@@ -335,9 +306,9 @@ impl NodeClient<'_> {
335
306
. send ( ) ;
336
307
337
308
if matches. is_present ( "return_testnet_credential" ) {
338
- result. expect ( "Error creating account for testnet node on our local node" ) ;
309
+ result? ;
339
310
Ok ( Response :: from (
340
- http:: Response :: builder ( ) . body ( token) . unwrap ( ) ,
311
+ http:: Response :: builder ( ) . body ( token) . unwrap ( ) , // infallible unwrap
341
312
) )
342
313
} else {
343
314
result. map_err ( Error :: ClientErr )
0 commit comments