| 58 | } |
| 59 | |
| 60 | pub async fn call(&mut self, req: Request) -> Result<Response, RpcError> { |
| 61 | trace!("Sending request {:?}", req); |
| 62 | |
| 63 | // Wrap the raw request in a well-formed JSON-RPC outer dict. |
| 64 | let id = self.next_id.fetch_add(1, Ordering::SeqCst); |
| 65 | let req: JsonRpc<Notification, Request> = JsonRpc::Request(json!(id), req); |
| 66 | let req = serde_json::to_value(req).map_err(|e| RpcError { |
| 67 | code: None, |
| 68 | message: format!("Error parsing request: {}", e), |
| 69 | })?; |
| 70 | let req2 = req.clone(); |
| 71 | self.write.send(req).await.map_err(|e| RpcError { |
| 72 | code: None, |
| 73 | message: format!("Error passing request to lightningd: {}", e), |
| 74 | })?; |
| 75 | |
| 76 | let mut response = self |
| 77 | .read |
| 78 | .next() |
| 79 | .await |
| 80 | .ok_or_else(|| RpcError { |
| 81 | code: None, |
| 82 | message: "no response from lightningd".to_string(), |
| 83 | })? |
| 84 | .map_err(|_| RpcError { |
| 85 | code: None, |
| 86 | message: "reading response from socket".to_string(), |
| 87 | })?; |
| 88 | trace!("Read response {:?}", response); |
| 89 | |
| 90 | // Annotate the response with the method from the request, so |
| 91 | // serde_json knows which variant of [`Request`] should be |
| 92 | // used. |
| 93 | response["method"] = req2["method"].clone(); |
| 94 | if let Some(_) = response.get("result") { |
| 95 | serde_json::from_value(response).map_err(|e| RpcError { |
| 96 | code: None, |
| 97 | message: format!("Malformed response from lightningd: {}", e), |
| 98 | }) |
| 99 | } else if let Some(e) = response.get("error") { |
| 100 | let e: RpcError = serde_json::from_value(e.clone()).unwrap(); |
| 101 | Err(e) |
| 102 | } else { |
| 103 | Err(RpcError { |
| 104 | code: None, |
| 105 | message: format!("Malformed response from lightningd: {}", response), |
| 106 | }) |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | pub async fn call_typed<R: IntoRequest>(&mut self, request: R) -> Result<R::Response, RpcError> { |
| 111 | Ok(self.call(request.into()) |