Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ utoipa-swagger-ui = { version = "9", features = ["rocket"] }
tokio = { version = "1", features = ["full"] }
alloy = { version = "=1.0.12", default-features = false, features = ["std", "serde"] }
async-trait = "0.1"
futures = "0.3"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
tracing-appender = "0.2"
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ enum StartupError {
routes::order::post_order_cancel,
routes::orders::get_orders_by_tx,
routes::orders::get_orders_by_address,
routes::orders::get_orders_by_token,
routes::trades::get_trades_by_tx,
routes::trades::get_trades_by_address,
routes::registry::get_registry,
Expand Down
8 changes: 5 additions & 3 deletions src/routes/order/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ impl<'a> OrderDataSource for RaindexOrderDataSource<'a> {
order_hash: Some(hash),
..Default::default()
};
self.client
.get_orders(None, Some(filters), None)
let result = self
.client
.get_orders(None, Some(filters), None, None)
.await
.map_err(|e| {
tracing::error!(error = %e, "failed to query orders");
ApiError::Internal("failed to query orders".into())
})
})?;
Ok(result.orders().to_vec())
}

async fn get_order_quotes(
Expand Down
87 changes: 0 additions & 87 deletions src/routes/orders.rs

This file was deleted.

46 changes: 46 additions & 0 deletions src/routes/orders/get_by_owner.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crate::auth::AuthenticatedKey;
use crate::error::{ApiError, ApiErrorResponse};
use crate::fairings::{GlobalRateLimit, TracingSpan};
use crate::types::common::ValidatedAddress;
use crate::types::orders::{OrdersListResponse, OrdersPaginationParams};
use rocket::serde::json::Json;
use rocket::State;
use tracing::Instrument;

#[utoipa::path(
get,
path = "/v1/orders/owner/{address}",
tag = "Orders",
security(("basicAuth" = [])),
params(
("address" = String, Path, description = "Owner address"),
OrdersPaginationParams,
),
responses(
(status = 200, description = "Paginated list of orders", body = OrdersListResponse),
(status = 400, description = "Bad request", body = ApiErrorResponse),
(status = 401, description = "Unauthorized", body = ApiErrorResponse),
(status = 429, description = "Rate limited", body = ApiErrorResponse),
(status = 500, description = "Internal server error", body = ApiErrorResponse),
)
)]
#[get("/owner/<address>?<params..>")]
pub async fn get_orders_by_address(
_global: GlobalRateLimit,
_key: AuthenticatedKey,
shared_raindex: &State<crate::raindex::SharedRaindexProvider>,
span: TracingSpan,
address: ValidatedAddress,
params: OrdersPaginationParams,
) -> Result<Json<OrdersListResponse>, ApiError> {
async move {
tracing::info!(address = ?address, params = ?params, "request received");
let raindex = shared_raindex.read().await;
raindex
.run_with_client(move |_client| async move { todo!() })
.await
.map_err(ApiError::from)?
}
.instrument(span.0)
.await
Comment on lines +36 to +45
Copy link

@coderabbitai coderabbitai bot Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Same todo!() panic risk as get_by_tx.rs — return a proper error instead.

This is a registered, client-reachable route. Replace todo!() with a graceful error response.

Proposed fix
     async move {
         tracing::info!(address = ?address, params = ?params, "request received");
-        let raindex = shared_raindex.read().await;
-        raindex
-            .run_with_client(move |_client| async move { todo!() })
-            .await
-            .map_err(ApiError::from)?
+        Err(ApiError::BadRequest("endpoint not yet implemented".into()))
     }
     .instrument(span.0)
     .await

As per coding guidelines: "Never use expect or unwrap in production code; handle errors gracefully or exit with a message".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async move {
tracing::info!(address = ?address, params = ?params, "request received");
let raindex = shared_raindex.read().await;
raindex
.run_with_client(move |_client| async move { todo!() })
.await
.map_err(ApiError::from)?
}
.instrument(span.0)
.await
async move {
tracing::info!(address = ?address, params = ?params, "request received");
Err(ApiError::BadRequest("endpoint not yet implemented".into()))
}
.instrument(span.0)
.await
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/routes/orders/get_by_owner.rs` around lines 36 - 45, Replace the
panic-inducing todo!() in the closure passed to raindex.run_with_client in
get_by_owner.rs with a graceful error result: have the closure return a Result
that uses the ApiError type (not panics) so the outer .map_err(ApiError::from)?
can propagate a client-friendly error; specifically modify the closure passed to
run_with_client to return Err(ApiError::appropriate_variant("descriptive
message")) (choose the correct ApiError constructor used elsewhere in the
codebase) instead of calling todo!(), ensuring the async block signature matches
run_with_client's expected Result type and the span.instrument usage remains
unchanged.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine as we are adding these endpoints one by one.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@findolor, understood! I appreciate the incremental approach for implementing these endpoints. The todo!() placeholders make sense as stubs while you build out each endpoint in separate iterations.


🧠 Learnings used
Learnt from: CR
Repo: ST0x-Technology/st0x.rest.api PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-19T09:28:42.183Z
Learning: Applies to **/*.rs : Keep OpenAPI annotations (`#[utoipa::path(...)]`) in sync when adding or modifying routes

Learnt from: findolor
Repo: ST0x-Technology/st0x.rest.api PR: 18
File: src/fairings/rate_limiter.rs:158-203
Timestamp: 2026-02-13T09:37:37.357Z
Learning: When multiple guards or layers write to the same cached rate-limit information, document and enforce the execution order so that the client-visible headers reflect the intended quota (global vs per-key). In this repo, rate-limiter.rs and auth-related guards intentionally write to the same CachedRateLimitInfo entry; ensure the per-key quota is what’s surfaced to clients and that the order is explicit in route signatures. Include tests that verify the final headers reflect the intended quota and that writes are intentional and auditable.

Learnt from: findolor
Repo: ST0x-Technology/st0x.rest.api PR: 38
File: src/routes/swap/mod.rs:115-129
Timestamp: 2026-02-17T09:35:57.431Z
Learning: In Rust server code for swap endpoints, if the response contains a non-empty approvals array, the behavior uses a two-phase flow: first the client sends an approval transaction, then queries the endpoint again to obtain the actual swap calldata. In the approval response, set to = approval.spender() to signal the eventual target, and set data = Bytes::new() (empty) to indicate 'no transaction yet.' Prefer this approach over using Address::ZERO for clarity. This pattern is specific to the swap flow in src/routes/swap/mod.rs and should be followed in similar swap-related endpoints with analogous approval semantics.

}
Loading