Cow instead of String

This commit is contained in:
Bryan Stitt 2023-05-30 23:17:05 -07:00
parent f1636d3b85
commit d64761403b
13 changed files with 108 additions and 90 deletions

@ -29,18 +29,16 @@ pub async fn query_admin_modify_usertier<'a>(
let user_address: Vec<u8> = params let user_address: Vec<u8> = params
.get("user_address") .get("user_address")
.ok_or_else(|| { .ok_or_else(|| {
Web3ProxyError::BadRequest("Unable to find user_address key in request".to_string()) Web3ProxyError::BadRequest("Unable to find user_address key in request".into())
})? })?
.parse::<Address>() .parse::<Address>()
.map_err(|_| { .map_err(|_| {
Web3ProxyError::BadRequest("Unable to parse user_address as an Address".to_string()) Web3ProxyError::BadRequest("Unable to parse user_address as an Address".into())
})? })?
.to_fixed_bytes() .to_fixed_bytes()
.into(); .into();
let user_tier_title = params.get("user_tier_title").ok_or_else(|| { let user_tier_title = params.get("user_tier_title").ok_or_else(|| {
Web3ProxyError::BadRequest( Web3ProxyError::BadRequest("Unable to get the user_tier_title key from the request".into())
"Unable to get the user_tier_title key from the request".to_string(),
)
})?; })?;
// Prepare output body // Prepare output body
@ -84,7 +82,7 @@ pub async fn query_admin_modify_usertier<'a>(
.one(&db_conn) .one(&db_conn)
.await? .await?
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"No user with this id found".to_string(), "No user with this id found".into(),
))?; ))?;
// Return early if the target user_tier_id is the same as the original user_tier_id // Return early if the target user_tier_id is the same as the original user_tier_id
response_body.insert( response_body.insert(
@ -98,7 +96,7 @@ pub async fn query_admin_modify_usertier<'a>(
.one(&db_conn) .one(&db_conn)
.await? .await?
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"User Tier name was not found".to_string(), "User Tier name was not found".into(),
))?; ))?;
if user.user_tier_id == new_user_tier.id { if user.user_tier_id == new_user_tier.id {

@ -739,6 +739,13 @@ impl Web3ProxyApp {
self.watch_consensus_head_receiver.clone() self.watch_consensus_head_receiver.clone()
} }
/// an ethers provider that you can use with ether's abigen.
/// this works for now, but I don't like it
/// TODO: I would much prefer we figure out the traits and `impl JsonRpcClient for Web3ProxyApp`
pub fn internal_provider(&self) -> &Arc<EthersHttpProvider> {
&self.internal_provider
}
pub async fn prometheus_metrics(&self) -> String { pub async fn prometheus_metrics(&self) -> String {
let globals = HashMap::new(); let globals = HashMap::new();
// TODO: what globals? should this be the hostname or what? // TODO: what globals? should this be the hostname or what?
@ -1417,19 +1424,19 @@ impl Web3ProxyApp {
.as_array() .as_array()
.ok_or_else(|| { .ok_or_else(|| {
Web3ProxyError::BadRequest( Web3ProxyError::BadRequest(
"Unable to get array from params".to_string(), "Unable to get array from params".into(),
) )
})? })?
.get(0) .get(0)
.ok_or_else(|| { .ok_or_else(|| {
Web3ProxyError::BadRequest( Web3ProxyError::BadRequest(
"Unable to get item 0 from params".to_string(), "Unable to get item 0 from params".into(),
) )
})? })?
.as_str() .as_str()
.ok_or_else(|| { .ok_or_else(|| {
Web3ProxyError::BadRequest( Web3ProxyError::BadRequest(
"Unable to get string from params item 0".to_string(), "Unable to get string from params item 0".into(),
) )
})?; })?;
@ -1546,7 +1553,7 @@ impl Web3ProxyApp {
.map_err(|x| { .map_err(|x| {
trace!("bad request: {:?}", x); trace!("bad request: {:?}", x);
Web3ProxyError::BadRequest( Web3ProxyError::BadRequest(
"param 0 could not be read as H256".to_string(), "param 0 could not be read as H256".into(),
) )
})?; })?;

@ -174,10 +174,10 @@ pub async fn block_needed(
// TODO: jsonrpc has a specific code for this // TODO: jsonrpc has a specific code for this
let obj = params let obj = params
.get_mut(0) .get_mut(0)
.ok_or_else(|| Web3ProxyError::BadRequest("invalid format. no params".to_string()))? .ok_or_else(|| Web3ProxyError::BadRequest("invalid format. no params".into()))?
.as_object_mut() .as_object_mut()
.ok_or_else(|| { .ok_or_else(|| {
Web3ProxyError::BadRequest("invalid format. params not object".to_string()) Web3ProxyError::BadRequest("invalid format. params not object".into())
})?; })?;
if obj.contains_key("blockHash") { if obj.contains_key("blockHash") {

@ -41,7 +41,7 @@ pub enum Web3ProxyError {
Anyhow(anyhow::Error), Anyhow(anyhow::Error),
#[error(ignore)] #[error(ignore)]
#[from(ignore)] #[from(ignore)]
BadRequest(String), BadRequest(Cow<'static, str>),
#[error(ignore)] #[error(ignore)]
#[from(ignore)] #[from(ignore)]
BadResponse(String), BadResponse(String),

@ -67,32 +67,30 @@ pub async fn admin_increase_balance(
let user_address: Address = params let user_address: Address = params
.get("user_address") .get("user_address")
.ok_or_else(|| { .ok_or_else(|| {
Web3ProxyError::BadRequest("Unable to find user_address key in request".to_string()) Web3ProxyError::BadRequest("Unable to find user_address key in request".into())
})? })?
.parse::<Address>() .parse::<Address>()
.map_err(|_| { .map_err(|_| {
Web3ProxyError::BadRequest("Unable to parse user_address as an Address".to_string()) Web3ProxyError::BadRequest("Unable to parse user_address as an Address".into())
})?; })?;
let user_address_bytes: Vec<u8> = user_address.to_fixed_bytes().into(); let user_address_bytes: Vec<u8> = user_address.to_fixed_bytes().into();
let note: String = params let note: String = params
.get("note") .get("note")
.ok_or_else(|| { .ok_or_else(|| Web3ProxyError::BadRequest("Unable to find 'note' key in request".into()))?
Web3ProxyError::BadRequest("Unable to find 'note' key in request".to_string())
})?
.parse::<String>() .parse::<String>()
.map_err(|_| { .map_err(|_| Web3ProxyError::BadRequest("Unable to parse 'note' as a String".into()))?;
Web3ProxyError::BadRequest("Unable to parse 'note' as a String".to_string())
})?;
// Get the amount from params // Get the amount from params
// Decimal::from_str // Decimal::from_str
let amount: Decimal = params let amount: Decimal = params
.get("amount") .get("amount")
.ok_or_else(|| { .ok_or_else(|| {
Web3ProxyError::BadRequest("Unable to get the amount key from the request".to_string()) Web3ProxyError::BadRequest("Unable to get the amount key from the request".into())
}) })
.map(|x| Decimal::from_str(x))? .map(|x| Decimal::from_str(x))?
.map_err(|err| { .map_err(|err| {
Web3ProxyError::BadRequest(format!("Unable to parse amount from the request {:?}", err)) Web3ProxyError::BadRequest(
format!("Unable to parse amount from the request {:?}", err).into(),
)
})?; })?;
let user_entry: user::Model = user::Entity::find() let user_entry: user::Model = user::Entity::find()
@ -100,7 +98,7 @@ pub async fn admin_increase_balance(
.one(&db_conn) .one(&db_conn)
.await? .await?
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"No user with this id found".to_string(), "No user with this id found".into(),
))?; ))?;
let increase_balance_receipt = admin_increase_balance_receipt::ActiveModel { let increase_balance_receipt = admin_increase_balance_receipt::ActiveModel {
@ -211,22 +209,22 @@ pub async fn admin_login_get(
let admin_address: Address = params let admin_address: Address = params
.get("admin_address") .get("admin_address")
.ok_or_else(|| { .ok_or_else(|| {
Web3ProxyError::BadRequest("Unable to find admin_address key in request".to_string()) Web3ProxyError::BadRequest("Unable to find admin_address key in request".into())
})? })?
.parse::<Address>() .parse::<Address>()
.map_err(|_err| { .map_err(|_err| {
Web3ProxyError::BadRequest("Unable to parse admin_address as an Address".to_string()) Web3ProxyError::BadRequest("Unable to parse admin_address as an Address".into())
})?; })?;
// Fetch the user_address parameter from the login string ... (as who we want to be logging in ...) // Fetch the user_address parameter from the login string ... (as who we want to be logging in ...)
let user_address: Vec<u8> = params let user_address: Vec<u8> = params
.get("user_address") .get("user_address")
.ok_or_else(|| { .ok_or_else(|| {
Web3ProxyError::BadRequest("Unable to find user_address key in request".to_string()) Web3ProxyError::BadRequest("Unable to find user_address key in request".into())
})? })?
.parse::<Address>() .parse::<Address>()
.map_err(|_err| { .map_err(|_err| {
Web3ProxyError::BadRequest("Unable to parse user_address as an Address".to_string()) Web3ProxyError::BadRequest("Unable to parse user_address as an Address".into())
})? })?
.to_fixed_bytes() .to_fixed_bytes()
.into(); .into();
@ -277,7 +275,7 @@ pub async fn admin_login_get(
.one(db_replica.as_ref()) .one(db_replica.as_ref())
.await? .await?
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"Could not find user in db".to_string(), "Could not find user in db".into(),
))?; ))?;
// TODO: Gotta check if encoding messes up things maybe ... // TODO: Gotta check if encoding messes up things maybe ...
@ -288,7 +286,7 @@ pub async fn admin_login_get(
.one(db_replica.as_ref()) .one(db_replica.as_ref())
.await? .await?
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"Could not find admin in db".to_string(), "Could not find admin in db".into(),
))?; ))?;
// Note that the admin is trying to log in as this user // Note that the admin is trying to log in as this user

@ -415,9 +415,9 @@ async fn handle_socket_payload(
Ok(response.into()) Ok(response.into())
} }
Err(err) => Err(Web3ProxyError::BadRequest(f!( Err(err) => Err(Web3ProxyError::BadRequest(
"incorrect params given for eth_unsubscribe. {err:?}" f!("incorrect params given for eth_unsubscribe. {err:?}").into(),
))), )),
} }
} }
_ => app _ => app

@ -352,10 +352,13 @@ pub async fn user_login_post(
.filter(referrer::Column::ReferralCode.eq(referral_code)) .filter(referrer::Column::ReferralCode.eq(referral_code))
.one(db_replica.as_ref()) .one(db_replica.as_ref())
.await? .await?
.ok_or(Web3ProxyError::BadRequest(format!( .ok_or(Web3ProxyError::BadRequest(
format!(
"The referral_link you provided does not exist {}", "The referral_link you provided does not exist {}",
referral_code referral_code
)))?; )
.into(),
))?;
// Create a new item in the database, // Create a new item in the database,
// marking this guy as the referrer (and ignoring a duplicate insert, if there is any...) // marking this guy as the referrer (and ignoring a duplicate insert, if there is any...)

@ -38,6 +38,8 @@ abigen!(
PaymentFactory, PaymentFactory,
r#"[ r#"[
event PaymentReceived(address indexed account, address token, uint256 amount) event PaymentReceived(address indexed account, address token, uint256 amount)
account_to_payment_address(address) -> address
payment_address_to_account(address) -> address
]"#, ]"#,
); );
@ -137,30 +139,31 @@ pub async fn user_balance_post(
// Let's say that for now, 1 credit is equivalent to 1 dollar (assuming any stablecoin has a 1:1 peg) // Let's say that for now, 1 credit is equivalent to 1 dollar (assuming any stablecoin has a 1:1 peg)
let tx_hash: H256 = params let tx_hash: H256 = params
.remove("tx_hash") .remove("tx_hash")
// TODO: map_err so this becomes a 500. routing must be bad
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"You have not provided the tx_hash in which you paid in".to_string(), "You have not provided a tx_hash".into(),
))? ))?
.parse() .parse()
.context("unable to parse tx_hash")?; .map_err(|err| {
Web3ProxyError::BadRequest(format!("unable to parse tx_hash: {}", err).into())
})?;
let db_conn = app.db_conn().context("query_user_stats needs a db")?; let db_conn = app.db_conn().context("query_user_stats needs a db")?;
// let db_replica = app
// .db_replica()
// .context("query_user_stats needs a db replica")?;
// Return straight false if the tx was already added ... // Return straight false if the tx was already added ...
// TODO: TxHash being string if increase_on_chain_balance_receipt::Entity::find()
let receipt = increase_on_chain_balance_receipt::Entity::find()
.filter(increase_on_chain_balance_receipt::Column::TxHash.eq(tx_hash.encode_hex())) .filter(increase_on_chain_balance_receipt::Column::TxHash.eq(tx_hash.encode_hex()))
.one(&db_conn) .one(&db_conn)
.await?; .await?
if receipt.is_some() { .is_some()
return Err(Web3ProxyError::BadRequest( {
"The transaction you provided has already been accounted for!".to_string(), let response = Json(json!({
)); "result": "success",
"message": "this transaction was already in the database",
}))
.into_response();
return Ok(response);
} }
debug!("Receipt: {:?}", receipt);
// Iterate through all logs, and add them to the transaction list if there is any // Iterate through all logs, and add them to the transaction list if there is any
// Address will be hardcoded in the config // Address will be hardcoded in the config
@ -170,18 +173,32 @@ pub async fn user_balance_post(
trace!("Transaction receipt: {:#?}", transaction_receipt); trace!("Transaction receipt: {:#?}", transaction_receipt);
// there is no need to check accepted tokens. the smart contract already does that // there is no need to check accepted tokens. the smart contract already reverts if the token isn't accepted
// parse the log from the transaction receipt to get the token address, let payment_factory_address = app
/* .config
event PaymentReceived: .deposit_factory_contract
account: indexed(address) .context("A deposit_contract must be provided in the config to parse payments")?;
token: address
amount: uint256 let payment_factory =
*/ PaymentFactory::new(payment_factory_address, app.internal_provider().clone());
// TODO: parse the log from the transaction receipt
// let deposit_log = payment_factory.payment_received_filter().topic;
// // // TODO: do a quick check that this transaction contains the required log
// if !transaction_receipt.logs_bloom.contains_input(deposit_log) {
// return Err(Web3ProxyError::BadRequest("no matching logs found".into()));
// }
// TODO: get the payment token address
// TODO: get the account the payment was received on behalf of (any account could have sent it)
// TODO: get the decimals for the token // TODO: get the decimals for the token
// TODO: payment_factory.payment_address_to_account(...).call();
// Go through all logs, this should prob capture it, // Go through all logs, this should prob capture it,
// At least according to this SE logs are just concatenations of the underlying types (like a struct..) // At least according to this SE logs are just concatenations of the underlying types (like a struct..)
// https://ethereum.stackexchange.com/questions/87653/how-to-decode-log-event-of-my-transaction-log // https://ethereum.stackexchange.com/questions/87653/how-to-decode-log-event-of-my-transaction-log
@ -380,8 +397,4 @@ pub async fn user_balance_post(
return Ok(response); return Ok(response);
} }
*/ */
Err(Web3ProxyError::BadRequest(
"No such transaction was found, or token is not supported!".to_string(),
))
} }

@ -111,7 +111,7 @@ pub async fn get_subusers(
.remove("rpc_key") .remove("rpc_key")
// TODO: map_err so this becomes a 500. routing must be bad // TODO: map_err so this becomes a 500. routing must be bad
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"You have not provided the 'rpc_key' whose access to modify".to_string(), "You have not provided the 'rpc_key' whose access to modify".into(),
))? ))?
.parse() .parse()
.context(format!("unable to parse rpc_key {:?}", params))?; .context(format!("unable to parse rpc_key {:?}", params))?;
@ -122,7 +122,7 @@ pub async fn get_subusers(
.one(db_replica.as_ref()) .one(db_replica.as_ref())
.await? .await?
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"The provided RPC key cannot be found".to_string(), "The provided RPC key cannot be found".into(),
))?; ))?;
// Get all secondary users that have access to this rpc key // Get all secondary users that have access to this rpc key
@ -188,7 +188,7 @@ pub async fn modify_subuser(
.remove("rpc_key") .remove("rpc_key")
// TODO: map_err so this becomes a 500. routing must be bad // TODO: map_err so this becomes a 500. routing must be bad
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"You have not provided the 'rpc_key' whose access to modify".to_string(), "You have not provided the 'rpc_key' whose access to modify".into(),
))? ))?
.parse::<Ulid>() .parse::<Ulid>()
.context(format!("unable to parse rpc_key {:?}", params))?; .context(format!("unable to parse rpc_key {:?}", params))?;
@ -198,7 +198,7 @@ pub async fn modify_subuser(
.remove("subuser_address") .remove("subuser_address")
// TODO: map_err so this becomes a 500. routing must be bad // TODO: map_err so this becomes a 500. routing must be bad
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"You have not provided the 'user_address' whose access to modify".to_string(), "You have not provided the 'user_address' whose access to modify".into(),
))? ))?
.parse() .parse()
.context(format!("unable to parse subuser_address {:?}", params))?; .context(format!("unable to parse subuser_address {:?}", params))?;
@ -209,14 +209,14 @@ pub async fn modify_subuser(
.remove("new_status") .remove("new_status")
// TODO: map_err so this becomes a 500. routing must be bad // TODO: map_err so this becomes a 500. routing must be bad
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"You have not provided the new_stats key in the request".to_string(), "You have not provided the new_stats key in the request".into(),
))? ))?
.as_str() .as_str()
{ {
"upsert" => Ok(true), "upsert" => Ok(true),
"remove" => Ok(false), "remove" => Ok(false),
_ => Err(Web3ProxyError::BadRequest( _ => Err(Web3ProxyError::BadRequest(
"'new_status' must be one of 'upsert' or 'remove'".to_string(), "'new_status' must be one of 'upsert' or 'remove'".into(),
)), )),
}?; }?;
@ -224,7 +224,7 @@ pub async fn modify_subuser(
.remove("new_role") .remove("new_role")
// TODO: map_err so this becomes a 500. routing must be bad // TODO: map_err so this becomes a 500. routing must be bad
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"You have not provided the new_role key in the request".to_string(), "You have not provided the new_role key in the request".into(),
))? ))?
.as_str() .as_str()
{ {
@ -235,7 +235,7 @@ pub async fn modify_subuser(
"admin" => Ok(Role::Admin), "admin" => Ok(Role::Admin),
"collaborator" => Ok(Role::Collaborator), "collaborator" => Ok(Role::Collaborator),
_ => Err(Web3ProxyError::BadRequest( _ => Err(Web3ProxyError::BadRequest(
"'new_role' must be one of 'owner', 'admin', 'collaborator'".to_string(), "'new_role' must be one of 'owner', 'admin', 'collaborator'".into(),
)), )),
}?; }?;
@ -253,13 +253,13 @@ pub async fn modify_subuser(
.one(db_replica.as_ref()) .one(db_replica.as_ref())
.await? .await?
.ok_or(Web3ProxyError::BadRequest( .ok_or(Web3ProxyError::BadRequest(
"Provided RPC key does not exist!".to_owned(), "Provided RPC key does not exist!".into(),
))?; ))?;
// Make sure that the user owns the rpc_key_entity // Make sure that the user owns the rpc_key_entity
if rpc_key_entity.user_id != user.id { if rpc_key_entity.user_id != user.id {
return Err(Web3ProxyError::BadRequest( return Err(Web3ProxyError::BadRequest(
"you must own the RPC for which you are giving permissions out".to_string(), "you must own the RPC for which you are giving permissions out".into(),
)); ));
} }
@ -308,7 +308,7 @@ pub async fn modify_subuser(
Some(subuser) => { Some(subuser) => {
if subuser.id == user.id { if subuser.id == user.id {
return Err(Web3ProxyError::BadRequest( return Err(Web3ProxyError::BadRequest(
"you cannot make a subuser out of yourself".to_string(), "you cannot make a subuser out of yourself".into(),
)); ));
} }

@ -224,7 +224,7 @@ pub fn get_query_window_seconds_from_params(
|query_window_seconds: &String| { |query_window_seconds: &String| {
// parse the given timestamp // parse the given timestamp
query_window_seconds.parse::<u64>().map_err(|_| { query_window_seconds.parse::<u64>().map_err(|_| {
Web3ProxyError::BadRequest("Unable to parse query_window_seconds".to_string()) Web3ProxyError::BadRequest("Unable to parse query_window_seconds".into())
}) })
}, },
) )
@ -259,7 +259,7 @@ pub fn get_stats_column_from_params(params: &HashMap<String, String>) -> Web3Pro
sum_response_millis, \ sum_response_millis, \
sum_credits_used, \ sum_credits_used, \
balance" balance"
.to_string(), .into(),
)), )),
} }
}, },

@ -84,7 +84,7 @@ impl JsonRpcRequestEnum {
Self::Batch(x) => match x.first() { Self::Batch(x) => match x.first() {
Some(x) => Ok(x.id.clone()), Some(x) => Ok(x.id.clone()),
None => Err(Web3ProxyError::BadRequest( None => Err(Web3ProxyError::BadRequest(
"no requests in the batch".to_string(), "no requests in the batch".into(),
)), )),
}, },
Self::Single(x) => Ok(x.id.clone()), Self::Single(x) => Ok(x.id.clone()),

@ -208,7 +208,7 @@ pub async fn query_user_stats<'a>(
// TODO: move getting the param and checking the bearer token into a helper function // TODO: move getting the param and checking the bearer token into a helper function
if let Some(rpc_key_id) = params.get("rpc_key_id") { if let Some(rpc_key_id) = params.get("rpc_key_id") {
let rpc_key_id = rpc_key_id.parse::<u64>().map_err(|e| { let rpc_key_id = rpc_key_id.parse::<u64>().map_err(|e| {
Web3ProxyError::BadRequest(format!("Unable to parse rpc_key_id. {:?}", e)) Web3ProxyError::BadRequest(format!("Unable to parse rpc_key_id. {}", e).into())
})?; })?;
response_body.insert("rpc_key_id", serde_json::Value::Number(rpc_key_id.into())); response_body.insert("rpc_key_id", serde_json::Value::Number(rpc_key_id.into()));

@ -33,18 +33,18 @@ pub async fn query_user_stats<'a>(
params: &'a HashMap<String, String>, params: &'a HashMap<String, String>,
stat_response_type: StatType, stat_response_type: StatType,
) -> Web3ProxyResponse { ) -> Web3ProxyResponse {
let user_id = match bearer { let (user_id, _semaphore) = match bearer {
Some(inner_bearer) => { Some(TypedHeader(Authorization(bearer))) => {
let (user, _semaphore) = app.bearer_is_authorized(inner_bearer.0 .0).await?; let (user, semaphore) = app.bearer_is_authorized(bearer).await?;
user.id (user.id, Some(semaphore))
} }
None => 0, None => (0, None),
}; };
// Return an error if the bearer is set, but the StatType is Detailed // Return an error if the bearer is **not** set, but the StatType is Detailed
if stat_response_type == StatType::Detailed && user_id == 0 { if stat_response_type == StatType::Detailed && user_id == 0 {
return Err(Web3ProxyError::BadRequest( return Err(Web3ProxyError::BadRequest(
"Detailed Stats Response requires you to authorize with a bearer token".to_owned(), "Detailed Stats Response requires you to authorize with a bearer token".into(),
)); ));
} }
@ -66,8 +66,7 @@ pub async fn query_user_stats<'a>(
// Return a bad request if query_start == query_stop, because then the query is empty basically // Return a bad request if query_start == query_stop, because then the query is empty basically
if query_start == query_stop { if query_start == query_stop {
return Err(Web3ProxyError::BadRequest( return Err(Web3ProxyError::BadRequest(
"Start and Stop date cannot be equal. Please specify a (different) start date." "Start and Stop date cannot be equal. Please specify a (different) start date.".into(),
.to_owned(),
)); ));
} }
@ -128,7 +127,7 @@ pub async fn query_user_stats<'a>(
if user_rpc_keys.is_empty() { if user_rpc_keys.is_empty() {
return Err(Web3ProxyError::BadRequest( return Err(Web3ProxyError::BadRequest(
"User has no secret RPC keys yet".to_string(), "User has no secret RPC keys yet".into(),
)); ));
} }
@ -481,7 +480,7 @@ pub async fn query_user_stats<'a>(
if let Some(rpc_key_id) = params.get("rpc_key_id") { if let Some(rpc_key_id) = params.get("rpc_key_id") {
let rpc_key_id = rpc_key_id let rpc_key_id = rpc_key_id
.parse::<u64>() .parse::<u64>()
.map_err(|_| Web3ProxyError::BadRequest("Unable to parse rpc_key_id".to_string()))?; .map_err(|_| Web3ProxyError::BadRequest("Unable to parse rpc_key_id".into()))?;
response_body.insert("rpc_key_id", serde_json::Value::Number(rpc_key_id.into())); response_body.insert("rpc_key_id", serde_json::Value::Number(rpc_key_id.into()));
} }