Skip to content

Commit

Permalink
Better wrappers + send tx
Browse files Browse the repository at this point in the history
  • Loading branch information
Dzejkop committed Jun 4, 2024
1 parent c12a5d3 commit ca4e111
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 57 deletions.
87 changes: 44 additions & 43 deletions src/new_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::service::Service;
use crate::task_runner::TaskRunner;
use crate::types::{
CreateRelayerRequest, CreateRelayerResponse, NetworkInfo, NewNetworkInfo,
RelayerInfo, RelayerUpdate, SendTxResponse,
RelayerInfo, RelayerUpdate, SendTxRequest, SendTxResponse,
};

mod security;
Expand Down Expand Up @@ -262,52 +262,53 @@ impl RelayerApi {
&self,
Data(app): Data<&Arc<App>>,
Path(api_token): Path<ApiKey>,
// Json(req): Json<SendTxRequest>,
Json(req): Json<SendTxRequest>,
) -> Result<Json<SendTxResponse>> {
api_token.validate(app).await?;

// let tx_id = if let Some(id) = req.tx_id {
// id
// } else {
// uuid::Uuid::new_v4().to_string()
// };

// let relayer = app.db.get_relayer(api_token.relayer_id()).await?;

// if !relayer.enabled {
// return Err(ApiError::RelayerDisabled);
// }

// let relayer_queued_tx_count = app
// .db
// .get_relayer_pending_txs(api_token.relayer_id())
// .await?;

// if relayer_queued_tx_count > relayer.max_queued_txs as usize {
// return Err(ApiError::TooManyTransactions {
// max: relayer.max_queued_txs as usize,
// current: relayer_queued_tx_count,
// });
// }

// app.db
// .create_transaction(
// &tx_id,
// req.to,
// req.data.as_ref().map(|d| &d[..]).unwrap_or(&[]),
// req.value,
// req.gas_limit,
// req.priority,
// req.blobs,
// api_token.relayer_id(),
// )
// .await?;

// tracing::info!(tx_id, "Transaction created");

// Ok(Json(SendTxResponse { tx_id }))
let tx_id = if let Some(id) = req.tx_id {
id
} else {
uuid::Uuid::new_v4().to_string()
};

todo!()
let relayer = app.db.get_relayer(api_token.relayer_id()).await?;

if !relayer.enabled {
return Err(poem::error::Error::from_string(
"Relayer is disabled".to_string(),
StatusCode::FORBIDDEN,
));
}

let relayer_queued_tx_count = app
.db
.get_relayer_pending_txs(api_token.relayer_id())
.await?;

if relayer_queued_tx_count > relayer.max_queued_txs as usize {
return Err(poem::error::Error::from_string(
"Relayer queue is full".to_string(),
StatusCode::TOO_MANY_REQUESTS,
));
}

app.db
.create_transaction(
&tx_id,
req.to.0,
req.data.as_ref().map(|d| &d.0[..]).unwrap_or(&[]),
req.value.0,
req.gas_limit.0,
req.priority,
req.blobs,
api_token.relayer_id(),
)
.await?;

tracing::info!(tx_id, "Transaction created");

Ok(Json(SendTxResponse { tx_id }))
}

/// Get Transaction
Expand Down
20 changes: 13 additions & 7 deletions src/types.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use poem_openapi::Object;
use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
use sqlx::prelude::FromRow;
use wrappers::address::AddressWrapper;
use wrappers::hex_bytes::HexBytes;
use wrappers::hex_u256::HexU256;

pub mod wrappers;

#[derive(Deserialize, Serialize, Debug, Clone, Copy, Default, sqlx::Type)]
#[derive(Deserialize, Serialize, Debug, Clone, Copy, Default, sqlx::Type, Enum)]
#[serde(rename_all = "camelCase")]
#[oai(rename_all = "camelCase")]
#[sqlx(type_name = "transaction_priority", rename_all = "camelCase")]
pub enum TransactionPriority {
// 5th percentile
Expand Down Expand Up @@ -113,7 +115,6 @@ pub struct CreateRelayerRequest {
pub struct CreateRelayerResponse {
/// ID of the created relayer
pub relayer_id: String,
// TODO: Make type safe
/// Address of the created relayer
pub address: AddressWrapper,
}
Expand All @@ -124,14 +125,19 @@ pub struct CreateRelayerResponse {
pub struct SendTxRequest {
pub to: AddressWrapper,
pub value: HexU256,
// #[serde(default)]
// pub data: Option<Bytes>,
#[serde(default)]
#[oai(default)]
pub data: Option<HexBytes>,
pub gas_limit: HexU256,
// #[serde(default)]
// pub priority: TransactionPriority,
#[serde(default)]
#[oai(default)]
pub priority: TransactionPriority,
#[serde(default)]
#[oai(default)]
pub tx_id: Option<String>,
// TODO: poem_openapi thinks this is a nested array of numbers
#[serde(default, with = "crate::serde_utils::base64_binary")]
#[oai(default)]
pub blobs: Option<Vec<Vec<u8>>>,
}

Expand Down
1 change: 1 addition & 0 deletions src/types/wrappers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use hex_u256::HexU256;

pub mod address;
pub mod h256;
pub mod hex_bytes;

// TODO: Remove repeated code in these 2 modules
pub mod decimal_u256;
Expand Down
10 changes: 6 additions & 4 deletions src/types/wrappers/decimal_u256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,19 @@ impl poem_openapi::types::Type for DecimalU256 {
}

fn schema_ref() -> MetaSchemaRef {

Check warning on line 96 in src/types/wrappers/decimal_u256.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/tx-sitter-monolith/tx-sitter-monolith/src/types/wrappers/decimal_u256.rs
let mut schema_ref = MetaSchema::new_with_format("string", "u256");
let mut schema_ref = MetaSchema::new_with_format("u256", "decimal");

schema_ref.example =
Some(serde_json::Value::String("0xff".to_string()));
schema_ref.title = Some("Address".to_string());
Some(serde_json::Value::String("0".to_string()));
schema_ref.default =
Some(serde_json::Value::String("0".to_string()));
schema_ref.title = Some("Decimal U256".to_string());
schema_ref.description = Some(
"A 256-bit unsigned integer. Supports hex and decimal encoding",
);

MetaSchemaRef::Inline(Box::new(MetaSchema::new_with_format(
"string", "u256",
"u256", "decimal",
)))
}

Expand Down
86 changes: 86 additions & 0 deletions src/types/wrappers/hex_bytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use ethers::types::Bytes;

Check warning on line 1 in src/types/wrappers/hex_bytes.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/tx-sitter-monolith/tx-sitter-monolith/src/types/wrappers/hex_bytes.rs
use serde::{Deserialize, Serialize};
use poem_openapi::registry::{MetaSchema, MetaSchemaRef};
use poem_openapi::types::{ParseFromJSON, ToJSON};

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(transparent)]
pub struct HexBytes(pub Bytes);

impl From<Bytes> for HexBytes {
fn from(value: Bytes) -> Self {
Self(value)
}
}

impl poem_openapi::types::Type for HexBytes {
const IS_REQUIRED: bool = true;

type RawValueType = Self;

type RawElementValueType = Self;

fn name() -> std::borrow::Cow<'static, str> {
"string(bytes)".into()
}

fn schema_ref() -> MetaSchemaRef {

Check warning on line 27 in src/types/wrappers/hex_bytes.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/tx-sitter-monolith/tx-sitter-monolith/src/types/wrappers/hex_bytes.rs
let mut schema_ref = MetaSchema::new_with_format("string", "bytes");

schema_ref.example = Some(serde_json::Value::String(
"0xffffff".to_string(),
));
schema_ref.title = Some("Bytes".to_string());
schema_ref.description = Some("Hex encoded binary blob");

MetaSchemaRef::Inline(Box::new(MetaSchema::new_with_format(
"string", "bytes",
)))
}

fn as_raw_value(&self) -> Option<&Self::RawValueType> {
Some(self)
}

fn raw_element_iter<'a>(
&'a self,
) -> Box<dyn Iterator<Item = &'a Self::RawElementValueType> + 'a> {
Box::new(self.as_raw_value().into_iter())
}
}

impl ParseFromJSON for HexBytes {
fn parse_from_json(
value: Option<serde_json::Value>,
) -> poem_openapi::types::ParseResult<Self> {
// TODO: Better error handling
let value = value
.ok_or_else(|| poem_openapi::types::ParseError::expected_input())?;

let inner = serde_json::from_value(value)
.map_err(|_| poem_openapi::types::ParseError::expected_input())?;

Ok(Self(inner))
}
}

impl ToJSON for HexBytes {
fn to_json(&self) -> Option<serde_json::Value> {
serde_json::to_value(&self.0).ok()
}
}

Check warning on line 72 in src/types/wrappers/hex_bytes.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/tx-sitter-monolith/tx-sitter-monolith/src/types/wrappers/hex_bytes.rs
#[cfg(test)]
mod tests {
use super::*;
use test_case::test_case;

#[test_case("0xff", vec![255])]
#[test_case("0xffff", vec![255, 255])]
#[test_case("0x0101", vec![1, 1])]
fn deserialize_string(s: &str, v: Vec<u8>) {
let value = serde_json::Value::String(s.to_string());
let result = HexBytes::parse_from_json(Some(value)).unwrap();
assert_eq!(result.0, Bytes::from(v));
}
}
9 changes: 6 additions & 3 deletions src/types/wrappers/hex_u256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,19 @@ impl poem_openapi::types::Type for HexU256 {
}

fn schema_ref() -> MetaSchemaRef {

Check warning on line 74 in src/types/wrappers/hex_u256.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/tx-sitter-monolith/tx-sitter-monolith/src/types/wrappers/hex_u256.rs
let mut schema_ref = MetaSchema::new_with_format("string", "u256");
let mut schema_ref = MetaSchema::new_with_format("u256", "hex");

schema_ref.example = Some(serde_json::Value::String(
"0xff".to_string(),
));
schema_ref.title = Some("Address".to_string());
schema_ref.default = Some(serde_json::Value::String(
"0x0".to_string(),
));
schema_ref.title = Some("Hex U256".to_string());
schema_ref.description = Some("A 256-bit unsigned integer. Supports hex and decimal encoding");

MetaSchemaRef::Inline(Box::new(MetaSchema::new_with_format(
"string", "u256",
"u256", "hex",
)))
}

Expand Down

0 comments on commit ca4e111

Please sign in to comment.