From 20fe3ad5578f93762a93986268519b0696e3da09 Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Tue, 27 Feb 2024 16:21:08 +0100 Subject: [PATCH] Update errors in client + update logic --- src/client.rs | 57 ++++++++++++++++++++++++++---------- src/db.rs | 34 +++++++++++++++++---- src/server.rs | 2 +- src/server/routes/relayer.rs | 8 ++--- 4 files changed, 75 insertions(+), 26 deletions(-) diff --git a/src/client.rs b/src/client.rs index 2e6a35f..c92f639 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,4 +1,5 @@ use reqwest::Response; +use thiserror::Error; use crate::api_key::ApiKey; use crate::server::routes::network::NewNetworkInfo; @@ -8,6 +9,7 @@ use crate::server::routes::relayer::{ use crate::server::routes::transaction::{ GetTxResponse, SendTxRequest, SendTxResponse, }; +use crate::server::ApiError; use crate::types::RelayerUpdate; pub struct TxSitterClient { @@ -15,6 +17,21 @@ pub struct TxSitterClient { url: String, } +#[derive(Debug, Error)] +pub enum ClientError { + #[error("Reqwest error: {0}")] + Reqwest(#[from] reqwest::Error), + + #[error("Serialization error: {0}")] + Serde(#[from] serde_json::Error), + + #[error("API error: {0}")] + TxSitter(#[from] ApiError), + + #[error("Invalid API key: {0}")] + InvalidApiKey(eyre::Error), +} + impl TxSitterClient { pub fn new(url: impl ToString) -> Self { Self { @@ -23,7 +40,7 @@ impl TxSitterClient { } } - async fn post(&self, url: &str) -> eyre::Result + async fn post(&self, url: &str) -> Result where R: serde::de::DeserializeOwned, { @@ -34,7 +51,11 @@ impl TxSitterClient { Ok(response.json().await?) } - async fn json_post(&self, url: &str, body: T) -> eyre::Result + async fn json_post( + &self, + url: &str, + body: T, + ) -> Result where T: serde::Serialize, R: serde::de::DeserializeOwned, @@ -46,7 +67,7 @@ impl TxSitterClient { Ok(response.json().await?) } - async fn json_get(&self, url: &str) -> eyre::Result + async fn json_get(&self, url: &str) -> Result where R: serde::de::DeserializeOwned, { @@ -57,19 +78,21 @@ impl TxSitterClient { Ok(response.json().await?) } - async fn validate_response(response: Response) -> eyre::Result { + async fn validate_response( + response: Response, + ) -> Result { if !response.status().is_success() { - let body = response.text().await?; - - return Err(eyre::eyre!("{body}")); + let body: ApiError = response.json().await?; + return Err(ClientError::TxSitter(body)); } Ok(response) } + pub async fn create_relayer( &self, req: &CreateRelayerRequest, - ) -> eyre::Result { + ) -> Result { self.json_post(&format!("{}/1/admin/relayer", self.url), req) .await } @@ -77,7 +100,7 @@ impl TxSitterClient { pub async fn create_relayer_api_key( &self, relayer_id: &str, - ) -> eyre::Result { + ) -> Result { self.post(&format!("{}/1/admin/relayer/{relayer_id}/key", self.url,)) .await } @@ -86,7 +109,7 @@ impl TxSitterClient { &self, relayer_id: &str, relayer_update: RelayerUpdate, - ) -> eyre::Result<()> { + ) -> Result<(), ClientError> { self.json_post( &format!("{}/1/admin/relayer/{relayer_id}", self.url), relayer_update, @@ -98,9 +121,13 @@ impl TxSitterClient { &self, api_key: &ApiKey, req: &SendTxRequest, - ) -> eyre::Result { + ) -> Result { self.json_post( - &format!("{}/1/api/{}/tx", self.url, api_key.reveal()?), + &format!( + "{}/1/api/{}/tx", + self.url, + api_key.reveal().map_err(ClientError::InvalidApiKey)? + ), req, ) .await @@ -110,11 +137,11 @@ impl TxSitterClient { &self, api_key: &ApiKey, tx_id: &str, - ) -> eyre::Result { + ) -> Result { self.json_get(&format!( "{}/1/api/{}/tx/{tx_id}", self.url, - api_key.reveal()?, + api_key.reveal().map_err(ClientError::InvalidApiKey)?, tx_id = tx_id )) .await @@ -124,7 +151,7 @@ impl TxSitterClient { &self, chain_id: u64, req: &NewNetworkInfo, - ) -> eyre::Result<()> { + ) -> Result<(), ClientError> { let response = self .client .post(&format!("{}/1/admin/network/{}", self.url, chain_id)) diff --git a/src/db.rs b/src/db.rs index 3671487..5d688ee 100644 --- a/src/db.rs +++ b/src/db.rs @@ -74,7 +74,15 @@ impl Database { ) -> eyre::Result<()> { let mut tx = self.pool.begin().await?; - if let Some(name) = &update.relayer_name { + let RelayerUpdate { + relayer_name, + max_inflight_txs, + max_queued_txs, + gas_price_limits, + enabled, + } = update; + + if let Some(name) = relayer_name { sqlx::query( r#" UPDATE relayers @@ -88,7 +96,7 @@ impl Database { .await?; } - if let Some(max_inflight_txs) = update.max_inflight_txs { + if let Some(max_inflight_txs) = max_inflight_txs { sqlx::query( r#" UPDATE relayers @@ -97,12 +105,12 @@ impl Database { "#, ) .bind(id) - .bind(max_inflight_txs as i64) + .bind(*max_inflight_txs as i64) .execute(tx.as_mut()) .await?; } - if let Some(max_queued_txs) = update.max_queued_txs { + if let Some(max_queued_txs) = max_queued_txs { sqlx::query( r#" UPDATE relayers @@ -111,12 +119,12 @@ impl Database { "#, ) .bind(id) - .bind(max_queued_txs as i64) + .bind(*max_queued_txs as i64) .execute(tx.as_mut()) .await?; } - if let Some(gas_price_limits) = &update.gas_price_limits { + if let Some(gas_price_limits) = gas_price_limits { sqlx::query( r#" UPDATE relayers @@ -130,6 +138,20 @@ impl Database { .await?; } + if let Some(enabled) = enabled { + sqlx::query( + r#" + UPDATE relayers + SET enabled = $2 + WHERE id = $1 + "#, + ) + .bind(id) + .bind(*enabled) + .execute(tx.as_mut()) + .await?; + } + tx.commit().await?; Ok(()) diff --git a/src/server.rs b/src/server.rs index 33001ff..3a9b9ac 100644 --- a/src/server.rs +++ b/src/server.rs @@ -13,10 +13,10 @@ use self::routes::transaction::{get_tx, get_txs, send_tx}; use self::trace_layer::MatchedPathMakeSpan; use crate::app::App; +mod error; mod middleware; pub mod routes; mod trace_layer; -mod error; pub use self::error::ApiError; diff --git a/src/server/routes/relayer.rs b/src/server/routes/relayer.rs index da87148..066f4ab 100644 --- a/src/server/routes/relayer.rs +++ b/src/server/routes/relayer.rs @@ -83,10 +83,10 @@ pub async fn update_relayer( State(app): State>, Path(relayer_id): Path, Json(req): Json, -) -> Result<(), ApiError> { +) -> Result, ApiError> { app.db.update_relayer(&relayer_id, &req).await?; - Ok(()) + Ok(Json(())) } #[tracing::instrument(skip(app))] @@ -115,10 +115,10 @@ pub async fn get_relayer( pub async fn purge_unsent_txs( State(app): State>, Path(relayer_id): Path, -) -> Result<(), ApiError> { +) -> Result, ApiError> { app.db.purge_unsent_txs(&relayer_id).await?; - Ok(()) + Ok(Json(())) } #[tracing::instrument(skip(app, api_token))]