diff --git a/simln-lib/src/eclair.rs b/simln-lib/src/eclair.rs index 33bcbd3..9266272 100644 --- a/simln-lib/src/eclair.rs +++ b/simln-lib/src/eclair.rs @@ -27,28 +27,40 @@ pub struct EclairConnection { pub api_password: String, } -pub struct EclairNode { +impl TryInto for EclairConnection { + type Error = LightningError; + + fn try_into(self) -> Result { + Ok(EclairClient { + base_url: Url::parse(&self.base_url) + .map_err(|err| LightningError::GetInfoError(err.to_string()))?, + api_username: self.api_password, + api_password: self.api_username, + http_client: Client::new(), + }) + } +} + +/// Handles interaction with the underlying eclair connection. +struct EclairClient { base_url: Url, api_username: String, api_password: String, http_client: Client, - info: NodeInfo, - network: Network, } -impl EclairNode { - async fn request_static Deserialize<'de>>( - client: &Client, - base_url: &Url, - api_username: &str, - api_password: &str, +impl EclairClient { + async fn request Deserialize<'de>>( + &self, endpoint: &str, params: Option>, ) -> Result> { - let url = base_url.join(endpoint)?; - let mut request = client + let url = self.base_url.join(endpoint)?; + + let mut request = self + .http_client .request(Method::POST, url) - .basic_auth(api_username, Some(api_password)); + .basic_auth(self.api_username.clone(), Some(self.api_password.clone())); if let Some(params) = params { let mut form = Form::new(); @@ -67,37 +79,22 @@ impl EclairNode { Ok(response) } +} - async fn request Deserialize<'de>>( - &self, - endpoint: &str, - params: Option>, - ) -> Result> { - EclairNode::request_static( - &self.http_client, - &self.base_url, - &self.api_username, - &self.api_password, - endpoint, - params, - ) - .await - } +pub struct EclairNode { + client: EclairClient, + info: NodeInfo, + network: Network, +} +impl EclairNode { pub async fn new(connection: EclairConnection) -> Result { - let base_url = Url::parse(&connection.base_url) + let client: EclairClient = connection.try_into()?; + + let info: GetInfoResponse = client + .request("getinfo", None) + .await .map_err(|err| LightningError::GetInfoError(err.to_string()))?; - let client = Client::new(); - let info: GetInfoResponse = EclairNode::request_static( - &client, - &base_url, - &connection.api_username, - &connection.api_password, - "getinfo", - None, - ) - .await - .map_err(|err| LightningError::GetInfoError(err.to_string()))?; let pubkey = PublicKey::from_str(info.node_id.as_str()) .map_err(|err| LightningError::GetInfoError(err.to_string()))?; let network = Network::from_str(match info.network.as_str() { @@ -113,10 +110,7 @@ impl EclairNode { let features = parse_json_to_node_features(&info.features); Ok(Self { - base_url, - api_username: connection.api_username, - api_password: connection.api_password, - http_client: client, + client, info: NodeInfo { pubkey, alias: info.alias, @@ -148,6 +142,7 @@ impl LightningNode for EclairNode { params.insert("amountMsat".to_string(), amount_msat.to_string()); params.insert("paymentHash".to_string(), hex::encode(preimage)); let uuid: String = self + .client .request("sendtonode", Some(params)) .await .map_err(|err| LightningError::SendPaymentError(err.to_string()))?; @@ -156,6 +151,7 @@ impl LightningNode for EclairNode { params.insert("paymentHash".to_string(), hex::encode(preimage)); params.insert("id".to_string(), uuid); let payment_parts: PaymentInfoResponse = self + .client .request("getsentinfo", Some(params)) .await .map_err(|_| LightningError::InvalidPaymentHash)?; @@ -182,7 +178,7 @@ impl LightningNode for EclairNode { let mut params = HashMap::new(); params.insert("paymentHash".to_string(), hex::encode(hash.0)); - let payment_parts: PaymentInfoResponse = self.request("getsentinfo", Some(params)) + let payment_parts: PaymentInfoResponse = self.client.request("getsentinfo", Some(params)) .await .map_err(|err| LightningError::TrackPaymentError(err.to_string()))?; @@ -210,6 +206,7 @@ impl LightningNode for EclairNode { params.insert("nodeId".to_string(), hex::encode(node_id.serialize())); let node_info: NodeResponse = self + .client .request("node", Some(params)) .await .map_err(|err| LightningError::GetNodeInfoError(err.to_string()))?; @@ -230,6 +227,7 @@ impl LightningNode for EclairNode { ); let channels: ChannelsResponse = self + .client .request("channels", Some(params)) .await .map_err(|err| LightningError::ListChannelsError(err.to_string()))?;