Repository: Explore-Beyond-Innovations/ZeroXBridge_Sequencer
Pull request #10: Feat: implement withdrawal request API endpoint
Author: login: OthmanImam
Created: 2025-03-24T18:42:27Z | Merged: 2025-03-29T22:59:50Z

This PR implements the POST and GET `/withdraw` endpoints to handle L2 withdrawal requests.

- POST `/withdraw` accepts a StarkNet public key and amount, generates a commitment hash, stores the request in PostgreSQL with "pending" status.
- GET `/withdraw` fetches all pending withdrawal requests.

Closes #2 (Implement Withdrawal Request API Endpoint) 


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced withdrawal endpoints for creating requests and retrieving pending withdrawals.
  
- **Refactor**
  - Enhanced logging and streamlined database connectivity for improved reliability.
  - Updated database migration processes to support the new withdrawal functionality.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Linked issue #2: Implement Withdrawal Request API Endpoint
### **Description 📹**  
Implement the **Withdrawal Request API Endpoint** to track user withdrawal requests on L2. The API should accept withdrawal requests, store them in PostgreSQL, mark them as "pending" for later processing, and expose an endpoint to fetch pending withdrawals.  

📍 **File:** `src/api/routes.rs`  
💡 **Context:**  
- Users request withdrawals on **L2**, and the sequencer needs to track them.  
- The API should accept withdrawal requests, validate inputs, and persist them in the database.  
- Withdrawals remain in a **"pending"** state until processed by the sequencer.  
- A `GET /withdraw` endpoint should be implemented to fetch pending withdrawals.  

---
### ✅ **Proposed Actions**
#### 1️⃣ Fork and Create a Branch  
```sh
git checkout -b fix-[issue-number]
```
---
#### 2️⃣ Implement Changes  
- **Issue Implementation:**  

- [ ] Implement `POST /withdraw` in `src/api/routes.rs`:  
  - Validate `starkPubKey` and `amount` inputs.  
  - Generate a **commitment hash** for the withdrawal request.  
  - Store withdrawal request in **PostgreSQL** with `"pending"` status.  
  - Return a response with the **commitment hash**.  

- [ ] Implement `GET /withdraw`:  
  - Fetch all **pending withdrawals** from PostgreSQL.  
  - Return the withdrawal list with user addresses, amounts, and statuses.  

- [ ] Add unit tests for:  
  - **Valid withdrawal requests** (successful requests).  
  - **Invalid withdrawal requests** (missing/incorrect fields).  
  - **GET /withdraw response validation** (correctly fetches pending withdrawals).  
---
#### 3️⃣ Run Tests and Commit Changes  
- Run all unit tests and confirm correct behavior.  
- Verify PostgreSQL persistence for withdrawals.  
- Validate response structure for both endpoints.  
- Commit with a clear message:  
```sh
git commit -m "Feat: implement withdrawal request API endpoint"
```
---
### 📋 **Required Guidelines**  
- **Assignment:** Submit a PR only if you are assigned to this issue.  
- **Closing the Issue:** Include in PR description:  
  ```sh
  Close #[issue_id]
  ```
- **Review Process:**  
  - Mark PR as ready for review after submission.  
  - Address requested changes promptly.  
- **Testing:** Ensure successful build compilation before PR.  
---
Thank you for your contribution! 🚀
Linked issue comments: user: login: lynaDev2
created_at: 2025-03-20T08:46:02Z
body: I’d like to apply to implement the Withdrawal Request API Endpoint. I have experience with RESTful APIs, PostgreSQL, and backend development, ensuring a robust solution.

Plan:
✔ POST /withdraw – Validate inputs, generate a commitment hash, and store the request as "pending."
✔ GET /withdraw – Retrieve all pending withdrawals.
✔ Testing – Cover valid/invalid requests and response validation.

I'm ready to start immediately and ensure high-quality implementation. Looking forward to your approval!
author_association: NONE
user: login: OthmanImam
created_at: 2025-03-20T14:31:44Z
body: Hi Sir,

I'm Usman Adamu, a full-stack developer.
I want to implement this task if assigned.
All guideline will be strictly followed.

ETA: 5Hrs

Best regards;
@OthmanImam
author_association: CONTRIBUTOR
user: login: Jagadeeshftw
created_at: 2025-03-21T09:44:10Z
body: 
**Hi, I’d love to take on this issue!** With my expertise in **Cairo, StarkNet, and smart contract development**, I can implement a clean and efficient solution.  

### 🚀 **Why Me?**  
- **Proven Blockchain Experience** – Hands-on work with **StarkNet, Solidity, and Rust**, building secure and optimized smart contracts.  
- **Open Source Contributor** – Actively contributed to **30+ open-source projects**, showcasing adaptability and collaboration.  
- **Efficient & Reliable** – I deliver **high-quality, production-ready solutions quickly**, ensuring security and scalability.  

### ⏱ **Timeline**  
I estimate completing this within **1 day**. Let me know if I can proceed!  

### 🌐 **My Profile**  
Check out my OnlyDust profile for more insights: [Jagadeeshftw on OnlyDust](https://app.onlydust.com/users/Jagadeeshftw/overview)  

Looking forward to contributing. 🚀
author_association: CONTRIBUTOR
user: login: ekumamatthew
created_at: 2025-03-21T16:58:46Z
body: May I pick this up?
author_association: NONE
user: login: jaykayudo
created_at: 2025-03-21T23:01:10Z
body: Could I take over this issue?
author_association: NONE
user: login: OthmanImam
created_at: 2025-03-29T23:10:28Z
body: Thank you Boss.
author_association: CONTRIBUTOR

Diff:
diff --git a/.env b/.env
new file mode 100644
index 0000000..371e295
--- /dev/null
+++ b/.env
@@ -0,0 +1 @@
+export DATABASE_URL=postgresql://zeroxbridge_owner:npg_DJL5WhK3PlBM@ep-royal-art-a5o74xlv-pooler.us-east-2.aws.neon.tech/zeroxbridge?sslmode=require
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 3fdf4f2..5a96f97 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
 /target
 .qodo
 .env
-.gitignore
\ No newline at end of file
+.gitignore
diff --git a/Cargo.lock b/Cargo.lock
index 79f0acb..54d548a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -112,9 +112,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
 
 [[package]]
 name = "axum"
-version = "0.8.1"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8"
+checksum = "de45108900e1f9b9242f7f2e254aa3e2c029c921c258fe9e6b4217eeebd54288"
 dependencies = [
  "axum-core",
  "bytes",
@@ -146,12 +146,12 @@ dependencies = [
 
 [[package]]
 name = "axum-core"
-version = "0.5.0"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df1362f362fd16024ae199c1970ce98f9661bf5ef94b9808fee734bc3698b733"
+checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6"
 dependencies = [
  "bytes",
- "futures-util",
+ "futures-core",
  "http 1.3.1",
  "http-body 1.0.1",
  "http-body-util",
diff --git a/Cargo.toml b/Cargo.toml
index 40368e4..c3ddc72 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,8 +7,8 @@ edition = "2021"
 config = "0.15.11"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0.133"
+axum = "0.8.3"
 anyhow = "1.0.95"
-axum = "0.8.1"
 tokio = { version = "1.44.1", features = ["full"] }
 sqlx = { version = "0.8.3", features = [
   "postgres",
diff --git a/migrations/20250324173653_create_withdrawals_table.sql b/migrations/20250324173653_create_withdrawals_table.sql
new file mode 100644
index 0000000..8ddc1d3
--- /dev/null
+++ b/migrations/20250324173653_create_withdrawals_table.sql
@@ -0,0 +1 @@
+-- Add migration script here
diff --git a/migrations/20250325082529_create_withdrawals_table.sql b/migrations/20250325082529_create_withdrawals_table.sql
new file mode 100644
index 0000000..0fcb4a2
--- /dev/null
+++ b/migrations/20250325082529_create_withdrawals_table.sql
@@ -0,0 +1,20 @@
+-- 1️⃣ First, create the ENUM type
+CREATE TYPE withdrawal_status AS ENUM ('pending', 'processed', 'failed');
+
+-- 2️⃣ Then, create the table
+CREATE TABLE IF NOT EXISTS withdrawals (
+    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+    stark_pub_key TEXT NOT NULL,
+    amount TEXT NOT NULL,
+    commitment_hash TEXT NOT NULL,
+    status withdrawal_status NOT NULL DEFAULT 'pending', -- Use ENUM type directly
+    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
+    updated_at TIMESTAMPTZ
+);
+
+-- 3️⃣ Add constraints & indexes
+ALTER TABLE withdrawals
+ADD CONSTRAINT unique_commitment_hash UNIQUE (commitment_hash);
+
+CREATE INDEX idx_withdrawals_status ON withdrawals(status);
+CREATE INDEX idx_withdrawals_stark_pub_key ON withdrawals(stark_pub_key);
diff --git a/src/api/handlers.rs b/src/api/handlers.rs
index b4b0699..6671a86 100644
--- a/src/api/handlers.rs
+++ b/src/api/handlers.rs
@@ -4,7 +4,17 @@ use sha2::{Digest, Sha256};
 use sqlx::PgPool;
 use uuid::Uuid;
 
-use crate::db::database::{get_pending_deposits, insert_deposit, Deposit};
+use crate::db::database::{
+    create_withdrawal as db_create_withdrawal, get_pending_deposits,
+    get_pending_withdrawals as db_get_pending_withdrawals, insert_deposit, Deposit, Withdrawal,
+};
+
+#[derive(Debug, Deserialize)]
+pub struct CreateWithdrawalRequest {
+    pub stark_pub_key: String,
+    pub amount: i64,
+    pub commitment_hash: String,
+}
 
 #[derive(Deserialize)]
 pub struct DepositRequest {
@@ -55,3 +65,37 @@ pub async fn handle_get_pending_deposits(
 
     Ok(Json(deposit))
 }
+
+pub async fn create_withdrawal(
+    Extension(pool): Extension<PgPool>,
+    Json(payload): Json<CreateWithdrawalRequest>,
+) -> Result<Json<Withdrawal>, (StatusCode, String)> {
+    let withdrawal = db_create_withdrawal(
+        &pool,
+        payload.stark_pub_key,
+        payload.amount,
+        payload.commitment_hash,
+    )
+    .await
+    .map_err(|err| {
+        (
+            StatusCode::INTERNAL_SERVER_ERROR,
+            format!("DB Error: {:?}", err),
+        )
+    })?;
+
+    Ok(Json(withdrawal))
+}
+
+pub async fn get_pending_withdrawals(
+    Extension(pool): Extension<PgPool>,
+) -> Result<Json<Vec<Withdrawal>>, (StatusCode, String)> {
+    let withdrawals = db_get_pending_withdrawals(&pool).await.map_err(|err| {
+        (
+            StatusCode::INTERNAL_SERVER_ERROR,
+            format!("DB Error: {:?}", err),
+        )
+    })?;
+
+    Ok(Json(withdrawals))
+}
diff --git a/src/api/mod.rs b/src/api/mod.rs
index 4c53d3d..c0c696a 100644
--- a/src/api/mod.rs
+++ b/src/api/mod.rs
@@ -1,2 +1,2 @@
 pub mod handlers;
-pub mod routes;
\ No newline at end of file
+pub mod routes;
diff --git a/src/api/routes.rs b/src/api/routes.rs
index d1af6c0..0ac75af 100644
--- a/src/api/routes.rs
+++ b/src/api/routes.rs
@@ -2,7 +2,9 @@ use axum::{routing::post, Extension, Router};
 use sqlx::PgPool;
 use std::sync::Arc;
 
-use crate::api::handlers::{handle_deposit_post, handle_get_pending_deposits};
+use crate::api::handlers::{
+    create_withdrawal, get_pending_withdrawals, handle_deposit_post, handle_get_pending_deposits,
+};
 
 #[derive(Clone)]
 pub struct AppState {
@@ -15,6 +17,10 @@ pub fn create_router(pool: Arc<PgPool>) -> Router {
             "/deposit",
             post(handle_deposit_post).get(handle_get_pending_deposits),
         )
+        .route(
+            "/withdrawals",
+            post(create_withdrawal).get(get_pending_withdrawals),
+        )
         .layer(Extension(pool))
 }
 
diff --git a/src/config.rs b/src/config.rs
index 4c18b3e..48a319f 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,3 +1,4 @@
+
 use config::{Config, Environment, File};
 use serde::{Deserialize, Serialize};
 use std::path::Path;
diff --git a/src/db/database.rs b/src/db/database.rs
index 69af6b3..e6c7c84 100644
--- a/src/db/database.rs
+++ b/src/db/database.rs
@@ -1,6 +1,16 @@
-use serde::{Serialize, Deserialize};
-use sqlx::FromRow;
-use sqlx::PgPool;
+use serde::{Deserialize, Serialize};
+use sqlx::{FromRow, PgPool};
+use uuid::Uuid;
+
+#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
+pub struct Withdrawal {
+    pub id: i32,
+    pub stark_pub_key: String,
+    pub amount: i64,
+    pub commitment_hash: String,
+    pub status: String,
+    pub created_at: chrono::NaiveDateTime,
+}
 
 #[derive(Debug, FromRow, Serialize, Deserialize)]
 pub struct Deposit {
@@ -12,6 +22,28 @@ pub struct Deposit {
     pub created_at: chrono::NaiveDateTime,
 }
 
+pub async fn insert_withdrawal(
+    pool: &PgPool,
+    stark_pub_key: &str,
+    amount: i64,
+    commitment_hash: &str,
+) -> Result<Uuid, sqlx::Error> {
+    let row = sqlx::query!(
+        r#"
+        INSERT INTO withdrawals (stark_pub_key, amount, commitment_hash, status)
+        VALUES ($1, $2, $3, 'pending')
+        RETURNING id
+        "#,
+        stark_pub_key,
+        amount,
+        commitment_hash
+    )
+    .fetch_one(pool)
+    .await?;
+
+    Ok(row.id)
+}
+
 pub async fn insert_deposit(
     pool: &PgPool,
     user_address: &str,
@@ -31,7 +63,38 @@ pub async fn insert_deposit(
     .fetch_one(pool)
     .await?;
 
-    Ok(row)
+    Ok(row.id)
+}
+
+pub async fn get_pending_withdrawals(pool: &PgPool) -> Result<Vec<Withdrawal>, sqlx::Error> {
+    sqlx::query_as!(
+        Withdrawal,
+        r#"SELECT * FROM withdrawals WHERE status = 'pending' ORDER BY created_at DESC"#
+    )
+    .fetch_all(pool)
+    .await
+}
+
+pub async fn create_withdrawal(
+    pool: &PgPool,
+    stark_pub_key: String,
+    amount: i64,
+    commitment_hash: String,
+) -> Result<Withdrawal, sqlx::Error> {
+    sqlx::query_as!(
+        Withdrawal,
+        r#"
+        INSERT INTO withdrawals (id, stark_pub_key, amount, commitment_hash, status)
+        VALUES ($1, $2, $3, $4, 'pending')
+        RETURNING *
+        "#,
+        Uuid::new_v4(),
+        stark_pub_key,
+        amount,
+        commitment_hash
+    )
+    .fetch_one(pool)
+    .await
 }
 
 pub async fn get_pending_deposits(pool: &PgPool) -> Result<Vec<Deposit>, sqlx::Error> {
@@ -43,4 +106,4 @@ pub async fn get_pending_deposits(pool: &PgPool) -> Result<Vec<Deposit>, sqlx::E
     .await?;
 
     Ok(deposits)
-}
\ No newline at end of file
+}
diff --git a/src/lib.rs b/src/lib.rs
index 82d10c7..82eee0e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,8 +1,7 @@
 pub mod api;
 pub mod config;
 pub mod db;
-
-mod queue {
+pub mod queue {
     pub mod l1_queue;
     pub mod l2_queue;
 }
diff --git a/src/main.rs b/src/main.rs
index f4fa61c..20029ea 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,6 +4,8 @@ use ethers::contract::Contract;
 use ethers::providers::{Http, Provider};
 use std::sync::Arc;
 use std::{net::SocketAddr, path::Path, sync::Arc};
+use tower_http::trace::TraceLayer;
+use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
 
 mod config;
 mod db;
@@ -16,6 +18,13 @@ use db::client::DBClient;
 async fn main() {
     let config = load_config(Some(Path::new("config.toml"))).expect("Failed to load config");
 
+    tracing_subscriber::registry()
+        .with(tracing_subscriber::EnvFilter::new(
+            std::env::var("RUST_LOG").unwrap_or_else(|_| "info".into()),
+        ))
+        .with(tracing_subscriber::fmt::layer())
+        .init();
+
     let l1_provider =
         Provider::<Http>::try_from(config.ethereum.rpc_url.clone()).expect("Invalid L1 RPC URL");
     let l2_provider =
@@ -38,7 +47,7 @@ async fn main() {
             .expect("TVL sync failed");
     });
 
-    let config = load_config(Some(Path::new("config.toml"))).expect("Failed to load config");
+    let pool = get_db_pool().await.expect("Failed to connect to database");
 
     let db = DBClient::new(&config)
         .await
diff --git a/tests/test_withdrawal_api.rs b/tests/test_withdrawal_api.rs
new file mode 100644
index 0000000..0fcad38
--- /dev/null
+++ b/tests/test_withdrawal_api.rs
@@ -0,0 +1,66 @@
+use axum::{body::Body, http::{Request, StatusCode}};
+use zeroxbridge_sequencer::api::{handlers::WithdrawalRequest, routes::create_test_app};
+use serde_json::json;
+use tower::ServiceExt; // for `app.oneshot()`
+
+#[tokio::test]
+async fn test_post_valid_withdrawal() {
+    let app = create_test_app().await;
+
+    let request = Request::builder()
+        .method("POST")
+        .uri("/withdraw")
+        .header("content-type", "application/json")
+        .body(Body::from(
+            json!({
+                "stark_pub_key": "0xabc123",
+                "amount": 5000
+            }).to_string(),
+        ))
+        .unwrap();
+
+    let response = app.oneshot(request).await.unwrap();
+    assert_eq!(response.status(), StatusCode::OK);
+
+    let body = hyper::body::to_bytes(response.into_body()).await.unwrap();
+    let parsed: serde_json::Value = serde_json::from_slice(&body).unwrap();
+    assert!(parsed.get("commitment_hash").is_some());
+}
+
+#[tokio::test]
+async fn test_post_invalid_withdrawal() {
+    let app = create_test_app().await;
+
+    let request = Request::builder()
+        .method("POST")
+        .uri("/withdraw")
+        .header("content-type", "application/json")
+        .body(Body::from(
+            json!({
+                "stark_pub_key": "",
+                "amount": -10
+            }).to_string(),
+        ))
+        .unwrap();
+
+    let response = app.oneshot(request).await.unwrap();
+    assert_eq!(response.status(), StatusCode::BAD_REQUEST);
+}
+
+#[tokio::test]
+async fn test_get_pending_withdrawals() {
+    let app = create_test_app().await;
+
+    let request = Request::builder()
+        .method("GET")
+        .uri("/withdraw")
+        .body(Body::empty())
+        .unwrap();
+
+    let response = app.oneshot(request).await.unwrap();
+    assert_eq!(response.status(), StatusCode::OK);
+
+    let body = hyper::body::to_bytes(response.into_body()).await.unwrap();
+    let parsed: serde_json::Value = serde_json::from_slice(&body).unwrap();
+    assert!(parsed.is_array());
+}
\ No newline at end of file


Reviews:
user: login: JoE11-y
body: Good job @OthmanImam.

Just a couple more adjustments and you're good to go
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T14:28:57Z
user: login: OthmanImam
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T15:47:19Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 7**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>migrations/20250324173653_create_withdrawals_table.sql (1)</summary><blockquote>

`1-2`: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**This migration file requires implementation.**

The file contains only a placeholder comment without actual SQL statements to create the withdrawals table. The PR objectives mention storing withdrawal requests in PostgreSQL, but this migration doesn't define the table structure.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if there's another migration file that might be implementing the withdrawals table
fd "create_withdrawals" migrations/
```

Length of output: 145

---

Let's check the content of the second migration file to determine whether it contains the actual SQL implementation for creating the withdrawals table. This information is vital in deciding if the placeholder file (20250324173653\_create\_withdrawals\_table.sql) needs to be updated or removed.

---

🏁 Script executed:

```shell
#!/bin/bash
cat migrations/20250325082529_create_withdrawals_table.sql
```

Length of output: 807

---



</details>

**Action Required: Remove or Update the Placeholder Migration File**

It appears that the file `migrations/20250324173653_create_withdrawals_table.sql` contains only a placeholder comment, while the actual implementation for creating the withdrawals table is correctly provided in `migrations/20250325082529_create_withdrawals_table.sql`. To avoid confusion and potential redundancy in your migration history, please remove or update the placeholder file.

- Verify if the placeholder migration file is intentionally kept (for example, as a rollback or reference) or if it was mistakenly left in the PR.
- If the placeholder is not needed, remove it.
- If it is needed, update it to reflect the intended migrations to avoid collision with the actual implementation.

</blockquote></details>

</blockquote></details>

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>.env (1)</summary><blockquote>

`1-1`: _⚠️ Potential issue_

**Security concern: Hard-coded database credentials should not be committed to source control.**

The `.env` file contains a database connection string with hard-coded credentials that should not be included in the repository. This is a serious security risk.



Please remove this file from version control and add it to your `.gitignore`. Instead, provide a `.env.example` file with placeholder values to guide developers on setting up their local environment.

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (10)</summary><blockquote>

<details>
<summary>.gitignore (1)</summary><blockquote>

`2-3`: **Fix duplicate entry and confirm .env addition.**

There appears to be a duplicate entry for `.qodo` on line 2. The addition of `.env` is good practice for security as it will prevent accidental commits of environment variables including the database connection string.

```diff
/target
-.qodo
.qodo
.env
```

</blockquote></details>
<details>
<summary>src/api/models.rs (1)</summary><blockquote>

`9-9`: **Consider using an enum for the status field.**

Using a string for status makes the code more prone to errors with inconsistent status values.


```diff
- pub status: String,
+ pub status: WithdrawalStatus,
```

And add an enum definition:

```rust
#[derive(Debug, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "withdrawal_status", rename_all = "lowercase")]
pub enum WithdrawalStatus {
    Pending,
    Processed,
    Failed,
}
```

This would provide type safety and prevent invalid status values.

</blockquote></details>
<details>
<summary>src/api/routes.rs (1)</summary><blockquote>

`1-23`: **Consider moving handler implementations to the handlers module.**

Since you've defined a handlers module in `src/api/mod.rs`, these handler implementations should be moved there to maintain clean separation of concerns.


Routes should only define the routing structure and reference handler functions from the handlers module rather than implementing them directly.

</blockquote></details>
<details>
<summary>tests/test_withdrawal_api.rs (3)</summary><blockquote>

`6-28`: **Consider verifying the response schema more thoroughly**
It might be helpful to assert the response body structure more explicitly (e.g., check JSON object keys, their required presence, and correct types) to ensure the endpoint returns the expected data format.

---

`30-48`: **Add more negative test coverage**
Testing an empty `stark_pub_key` and a negative `amount` is a good start. Consider adding more test cases to check for missing fields, invalid data types, or extremely large amounts to strengthen validation coverage.

---

`50-66`: **Validate the response body content**
While verifying that the response is an array is useful, also consider asserting on its contents or length to confirm that correct data, or no data, is returned when expected.

</blockquote></details>
<details>
<summary>src/config.rs (1)</summary><blockquote>

`4-12`: **Improve error handling for missing environment variables**
Currently, the code panics if `DATABASE_URL` is not set. Consider returning a user-friendly error or providing a fallback value to avoid abrupt failures in production environments.

</blockquote></details>
<details>
<summary>src/api/handlers.rs (1)</summary><blockquote>

`15-31`: **Consider logging creation success**
Adding an info-level log (e.g., “Withdrawal created successfully”) can help with operational visibility and debugging.

</blockquote></details>
<details>
<summary>src/main.rs (2)</summary><blockquote>

`17-17`: **Ensure dotenv loading is necessary in production.**

`dotenv().ok();` is handy for local development, but be cautious in production environments. Consider conditionally loading `.env` only in non-production modes to avoid accidental overrides.

---

`26-30`: **Validate database connectivity before proceeding.**

Using `get_db_pool` is a neat approach, but ensure that the application handles possible connectivity failures more gracefully (e.g., retries, logs, or user-friendly error messages).

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9c8c94f313f5169e47ed4f981950f3bffa92d6eb and 2189b5b76db9c095a0744601d00790ef9649da09.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `Cargo.lock` is excluded by `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (16)</summary>

* `.env` (1 hunks)
* `.gitignore` (1 hunks)
* `Cargo.toml` (1 hunks)
* `migrations/20250324173653_create_withdrawals_table.sql` (1 hunks)
* `migrations/20250325082529_create_withdrawals_table.sql` (1 hunks)
* `src/api/database.rs` (0 hunks)
* `src/api/handlers.rs` (1 hunks)
* `src/api/mod.rs` (1 hunks)
* `src/api/models.rs` (1 hunks)
* `src/api/routes.rs` (1 hunks)
* `src/config.rs` (1 hunks)
* `src/db/database.rs` (1 hunks)
* `src/db/mod.rs` (1 hunks)
* `src/lib.rs` (1 hunks)
* `src/main.rs` (1 hunks)
* `tests/test_withdrawal_api.rs` (1 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (1)</summary>

* src/api/database.rs

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (3)</summary>

<details>
<summary>src/api/handlers.rs (2)</summary><blockquote>

<details>
<summary>src/db/database.rs (2)</summary>

* `get_pending_withdrawals` (37-44)
* `create_withdrawal` (46-66)

</details>
<details>
<summary>src/api/routes.rs (2)</summary>

* `get_pending_withdrawals` (12-16)
* `create_withdrawal` (18-23)

</details>

</blockquote></details>
<details>
<summary>src/main.rs (3)</summary><blockquote>

<details>
<summary>src/api/routes.rs (1)</summary>

* `withdrawal_routes` (6-10)

</details>
<details>
<summary>src/config.rs (1)</summary>

* `get_db_pool` (4-12)

</details>
<details>
<summary>src/db/client.rs (1)</summary>

* `new` (16-25)

</details>

</blockquote></details>
<details>
<summary>src/db/database.rs (1)</summary><blockquote>

<details>
<summary>src/api/handlers.rs (2)</summary>

* `get_pending_withdrawals` (33-43)
* `create_withdrawal` (15-31)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (15)</summary><blockquote>

<details>
<summary>src/db/mod.rs (1)</summary>

`2-2`: **LGTM! Good modularization approach.**

Adding the database module publicly is a good approach for encapsulating the withdrawal functionality while maintaining separation of concerns.

</details>
<details>
<summary>src/lib.rs (1)</summary>

`1-4`: **LGTM! Well-structured library entry point.**

This is a clean and organized approach to structuring the library with clear separation of API, configuration, and database components. The modular design will facilitate easier maintenance and testing.

</details>
<details>
<summary>src/api/models.rs (1)</summary>

`3-11`: **LGTM: Well-structured Withdrawal model with appropriate derivations.**

The Withdrawal struct is properly defined with all necessary fields and uses appropriate data types. The derive macros enable serialization, deserialization, and database row mapping as needed.

</details>
<details>
<summary>src/api/mod.rs (1)</summary>

`1-4`: **LGTM: Modular structure for API components.**

Good organization of API components into separate modules for routes, handlers, database, and models, which promotes clean separation of concerns.

</details>
<details>
<summary>tests/test_withdrawal_api.rs (1)</summary>

`1-5`: **Looks good!**
No issues spotted with the initial imports and setup in this range.

</details>
<details>
<summary>src/api/handlers.rs (3)</summary>

`1-7`: **Imports are well-structured**
The imported items look concise and relevant to this module’s responsibilities.

---

`8-13`: **Revisit `amount` as a string**
Using a string for `amount` can complicate parsing and validation. Consider a numeric or fixed-precision type (like `i64` or `Decimal`) if arbitrary precision is needed.  

Would you like to explore using a decimal crate to handle large integer or fractional amounts accurately?

---

`33-43`: **Implementation appears solid**
This approach cleanly delegates SQL logic to the database module and returns pending withdrawals as expected.

</details>
<details>
<summary>src/main.rs (2)</summary>

`1-3`: **Good use of standard crates and concurrency setup.**

Using `Arc` for the shared database pool and referencing `sqlx` looks correct and safe for concurrency.

---

`45-50`: **Router creation is modular and clean.**

The `create_router` function properly composes routes and attaches middleware layers. This approach improves readability and maintainability.

</details>
<details>
<summary>migrations/20250325082529_create_withdrawals_table.sql (1)</summary>

`15-20`: **Indexes and constraints look good.**

Including constraints on `commitment_hash` and indexing `status` and `stark_pub_key` improves data integrity and query performance, respectively.

</details>
<details>
<summary>src/db/database.rs (1)</summary>

`37-44`: **Query for pending withdrawals is correct, but watch for type mismatches.**

This query naturally returns the entire row, including a UUID for `id`. Make sure your `Withdrawal` struct’s `id` field aligns with the database schema to avoid decoding issues.

</details>
<details>
<summary>Cargo.toml (3)</summary>

`8-9`: **Dependency Update: Serde and Serde_json**  
The update to use Serde with the `"derive"` feature is a good practice for enabling auto-derivation of serialization and deserialization. Simplifying the version specification for `serde_json` to `"1"` is acceptable and keeps things concise.

---

`13-23`: **New Dependencies for Logging, Cryptography, Database, and HTTP Server**  
The additional dependencies—including `tracing`, `sha2`, `uuid`, `chrono`, `hex`, `dotenvy`, `tracing-subscriber`, `tower-http`, `sqlx`, `hyper`, and `axum`—align well with the new withdrawal request API requirements. In particular:  
- **Axum version change:** Upgrading/downgrading to `axum = "0.6"` should be verified to ensure compatibility with your routing and middleware implementations for the new endpoints.  
- **SQLx and related features:** The updated `sqlx` dependency with the specified features (`runtime-tokio`, `postgres`, `uuid`, `chrono`, `tls-rustls`) is well chosen to support PostgreSQL interactions.  

Please double-check that all these dependencies work harmoniously together and that the downgrade of Axum is intentional.

---

`25-26`: **Development Dependency: sqlx-cli**  
The addition of `sqlx-cli` in the `[dev-dependencies]` section with version `"0.7"` and the appropriate feature for PostgreSQL will support managing migrations and other CLI database operations. This setup is clear and appropriate for development purposes.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-28T21:15:30Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro (Legacy)**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 2189b5b76db9c095a0744601d00790ef9649da09 and 2bd1b3b462b63d006b75c65ee046b2a05fa17ae1.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `Cargo.lock` is excluded by `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `Cargo.toml` (1 hunks)
* `src/config.rs` (1 hunks)
* `src/lib.rs` (1 hunks)
* `src/main.rs` (2 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* src/config.rs

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary>

* Cargo.toml
* src/lib.rs

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>src/main.rs (3)</summary><blockquote>

<details>
<summary>src/oracle_service/oracle_service.rs (1)</summary>

* `sync_tvl` (26-58)

</details>
<details>
<summary>src/api/routes.rs (1)</summary>

* `withdrawal_routes` (6-10)

</details>
<details>
<summary>src/db/client.rs (1)</summary>

* `new` (16-25)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>src/main.rs (5)</summary>

`1-8`: **Appropriate imports for the modular architecture**

The imports have been updated to support the new modular architecture with Axum, SQLx, and proper HTTP tracing. This is a good improvement for maintainability.

---

`14-17`: **Good modularization of API routes**

The introduction of the `api` module and importing withdrawal routes separately reflects a better separation of concerns, making the codebase more maintainable.

---

`21-21`: **Improve environment variable loading error handling**

The current implementation silently ignores `.env` file loading failures with `.ok()`. This could make debugging environment configuration issues difficult.


```diff
- dotenv().ok();
+ match dotenv() {
+     Ok(_) => tracing::debug!("Loaded environment variables from .env file"),
+     Err(e) => tracing::warn!("Failed to load .env file: {}", e),
+ }
```

Also, note that a previous review suggested keeping the `db` config setup for consistency with the rest of the codebase.

---

`50-53`: **Security consideration with network binding**

The server now binds to `0.0.0.0:3000` which exposes it on all network interfaces. Verify this is intentional - if the service should only be accessible locally, consider using `127.0.0.1:3000` instead.

---

`61-66`: **Good router organization with trace layer**

The new router creation function properly separates concerns and includes a trace layer for better observability. This is a good improvement.


One consideration based on the relevant snippets: The withdrawal routes in `src/api/routes.rs` use GET for creating withdrawals (`get(create_withdrawal)`), which isn't RESTful. Consider changing to POST for resource creation endpoints.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-28T22:50:46Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (4)</summary><blockquote>

<details>
<summary>src/main.rs (1)</summary><blockquote>

`21-23`: **Consider consolidating configuration approaches**

There appears to be a mix of configuration approaches - loading from environment variables via `dotenv()` and from a TOML file via `load_config()`. While this works, it may lead to confusion about where specific configuration values should be defined.


Consider moving toward a single configuration approach for better maintainability. You could either:
1. Move all configuration to environment variables, or
2. Have the TOML file load values from environment variables with defaults

This would provide a more consistent configuration experience across the application.

</blockquote></details>
<details>
<summary>src/db/database.rs (3)</summary><blockquote>

`15-35`: **Consider consolidating duplicative insert logic.**  
`insert_withdrawal` and `create_withdrawal` share overlapping responsibilities of inserting records into the same table. You may simplify testing and maintenance by consolidating insertion logic into a single function or by differentiating them more clearly if they truly serve distinct use cases.

---

`37-44`: **Add indexing for faster retrieval of pending withdrawals.**  
If you expect many withdrawal records, consider adding an index on the `status` column (and possibly `created_at`) to improve performance of queries filtering or ordering by these fields.

---

`46-66`: **Ensure consistent usage of insertion functions.**  
`create_withdrawal` returns the entire `Withdrawal` struct, while `insert_withdrawal` returns only `Uuid`. Verify that all call sites use the right function, or unify these approaches to standardize how newly inserted rows are returned in your codebase.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro (Legacy)**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 2bd1b3b462b63d006b75c65ee046b2a05fa17ae1 and 9eff8abca3bb130e76ebba5b9c9dd7a8d335f04e.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `src/api/routes.rs` (1 hunks)
* `src/db/database.rs` (1 hunks)
* `src/main.rs` (2 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* src/api/routes.rs

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>src/main.rs (3)</summary><blockquote>

<details>
<summary>src/oracle_service/oracle_service.rs (1)</summary>

* `sync_tvl` (26-58)

</details>
<details>
<summary>src/api/routes.rs (1)</summary>

* `withdrawal_routes` (6-10)

</details>
<details>
<summary>src/db/client.rs (1)</summary>

* `new` (16-25)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>src/main.rs (4)</summary>

`4-5`: **Environment variable configuration has been implemented correctly**

Good use of `dotenv` for loading environment variables. This is a more flexible approach for configuration management compared to hardcoded values. The `.ok()` call properly handles cases where a .env file might not exist, which is appropriate for different deployment environments.



Also applies to: 21-21

---

`42-50`: **Database migration issue has been properly addressed**

The implementation now explicitly runs migrations with proper error handling, which addresses the previous review comment about missing migrations. This ensures the database schema will be up-to-date when the application starts.

---

`56-61`: **Server binding issue resolved**

The previous duplicate server binding issue has been fixed. The code now only creates one binding that's used for serving the application.

---

`14-14`: **Good modular API structure**

The code has been restructured to use a more modular approach with the withdrawal routes being merged into the main router. The `create_router` function is well-designed, providing good separation of concerns and making the main function cleaner.



Also applies to: 16-17, 66-71

</details>
<details>
<summary>src/db/database.rs (1)</summary>

`1-13`: **Struct fields align well with the database schema.**  
The `Withdrawal` struct fields and types appear consistent with a typical table design for tracking withdrawals. Using `Uuid` for the `id` resolves previous conflicts, and `i64` for `amount` is appropriate for potential large values.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-29T04:31:20Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>src/api/handlers.rs (1)</summary><blockquote>

`91-102`: **Consider adding pagination or filtering for pending withdrawals.**

Returning all pending withdrawals at once might become slow or memory-intensive if the dataset grows large. Adding pagination parameters (e.g., limit/offset) to the endpoint can improve scalability.

</blockquote></details>
<details>
<summary>src/db/database.rs (4)</summary><blockquote>

`5-13`: **Consider defining `status` as an enum to enforce valid states.**

Right now, `status` is a string that can be anything—introducing an enum in the database or codebase helps avoid typos and invalid states.

---

`24-44`: **Consolidate insertion logic to reduce duplication.**

`insert_withdrawal` and `create_withdrawal` both insert a new withdrawal record with minimal differences. Keeping a single function, or making one call the other, eliminates duplicate paths and potential drift.

---

`68-75`: **Optionally list columns and consider pagination for large datasets.**

Selecting all columns with `SELECT *` can cause unexpected issues if table structure changes. Explicitly listing columns is safer. Also consider a pagination approach if the expected data size can grow significantly.

---

`77-97`: **Avoid duplication in `create_withdrawal` and `insert_withdrawal`.**

Both functions insert records into the `withdrawals` table. Consider merging them or delegating to a single insert helper, passing the ID in as needed.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro (Legacy)**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9eff8abca3bb130e76ebba5b9c9dd7a8d335f04e and 0e529613dd626d922df62c1d4ad8c386ac84bbd0.

</details>

<details>
<summary>📒 Files selected for processing (9)</summary>

* `.gitignore` (1 hunks)
* `Cargo.toml` (0 hunks)
* `src/api/handlers.rs` (2 hunks)
* `src/api/mod.rs` (1 hunks)
* `src/api/routes.rs` (2 hunks)
* `src/config.rs` (1 hunks)
* `src/db/database.rs` (4 hunks)
* `src/lib.rs` (1 hunks)
* `src/main.rs` (3 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (1)</summary>

* Cargo.toml

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (6)</summary>

* src/config.rs
* .gitignore
* src/api/routes.rs
* src/api/mod.rs
* src/main.rs
* src/lib.rs

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>src/db/database.rs (1)</summary><blockquote>

<details>
<summary>src/api/handlers.rs (2)</summary>

* `get_pending_withdrawals` (91-102)
* `create_withdrawal` (70-89)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>src/api/handlers.rs (3)</summary>

`1-1`: **Looks good importing the `Withdrawal` model here.**

No issues found. This import aligns with usage in this file.

---

`8-11`: **Dependency imports from `database` are consistent with recommended separation of concerns.**

Pulling these functions from `src/db/database.rs` is in line with modular organization. Good job referencing these helper routines rather than embedding raw queries in the handlers.

---

`13-18`: **Verify user-supplied `commitment_hash` input.**

The request struct allows the client to provide the commitment hash, whereas deposit logic typically generates the hash server-side. Ensure that trust in the caller-supplied hash is acceptable or, if not, consider generating it in the backend.  

Would you like a script to scan the codebase for any references to `commitment_hash` to confirm consistent usage?

</details>
<details>
<summary>src/db/database.rs (2)</summary>

`1-3`: **No issues with these new imports.**

They are necessary for the upcoming logic and data structures.

---

`65-66`: **Updated return statement looks correct.**

This properly returns `row.id` for the newly inserted deposit record.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-29T22:21:21Z
user: login: JoE11-y
body: Thank you for your contribution @OthmanImam 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-29T22:59:41Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>♻️ Duplicate comments (2)</summary><blockquote>

<details>
<summary>src/api/handlers.rs (1)</summary><blockquote>

`69-88`: _⚠️ Potential issue_

**Add input validation for withdrawal creation.**

Unlike the deposit endpoint, there are no validation checks for negative/zero amounts or empty public keys. This could lead to invalid records in the database.



Add validation similar to the deposit handler:

```diff
pub async fn create_withdrawal(
    Extension(pool): Extension<PgPool>,
    Json(payload): Json<CreateWithdrawalRequest>,
) -> Result<Json<Withdrawal>, (StatusCode, String)> {
+    if payload.amount <= 0 || payload.stark_pub_key.trim().is_empty() || payload.commitment_hash.trim().is_empty() {
+        return Err((
+            StatusCode::BAD_REQUEST,
+            "Invalid withdrawal parameters".to_string(),
+        ));
+    }
+
    let withdrawal = db_create_withdrawal(
        &pool,
        payload.stark_pub_key,
        payload.amount,
        payload.commitment_hash,
    )
    .await
    .map_err(|err| {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("DB Error: {:?}", err),
        )
    })?;

    Ok(Json(withdrawal))
}
```

</blockquote></details>
<details>
<summary>src/db/database.rs (1)</summary><blockquote>

`5-13`: _⚠️ Potential issue_

**Fix type mismatch between Withdrawal struct and database schema.**

The `id` field is defined as `i32`, but your database operations use and return `Uuid`. This will cause runtime errors or type conflicts.



Adjust the struct to use a compatible type:

```diff
#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
pub struct Withdrawal {
-    pub id: i32,
+    pub id: uuid::Uuid,
    pub stark_pub_key: String,
    pub amount: i64,
    pub commitment_hash: String,
    pub status: String,
    pub created_at: chrono::NaiveDateTime,
}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>src/api/handlers.rs (1)</summary><blockquote>

`90-101`: **Consider standardizing error message formatting.**

While the error handling is correct, there's inconsistency in how errors are formatted compared to `handle_get_pending_deposits`. The withdrawal handler uses "DB Error: {:?}" while the deposit handler simply passes the error string.


Either standardize on one approach or extract error handling into a helper function for consistency:

```diff
pub async fn get_pending_withdrawals(
    Extension(pool): Extension<PgPool>,
) -> Result<Json<Vec<Withdrawal>>, (StatusCode, String)> {
    let withdrawals = db_get_pending_withdrawals(&pool).await.map_err(|err| {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
-            format!("DB Error: {:?}", err),
+            err.to_string(),
        )
    })?;

    Ok(Json(withdrawals))
}
```

</blockquote></details>
<details>
<summary>src/db/database.rs (1)</summary><blockquote>

`69-76`: **Consider adding pagination to get_pending_withdrawals.**

As the number of pending withdrawals grows, fetching all records could become inefficient. Consider implementing pagination for better performance.


```diff
pub async fn get_pending_withdrawals(
    pool: &PgPool, 
+    limit: i64, 
+    offset: i64
) -> Result<Vec<Withdrawal>, sqlx::Error> {
    sqlx::query_as!(
        Withdrawal,
-        r#"SELECT * FROM withdrawals WHERE status = 'pending' ORDER BY created_at DESC"#
+        r#"SELECT * FROM withdrawals WHERE status = 'pending' ORDER BY created_at DESC LIMIT $1 OFFSET $2"#,
+        limit,
+        offset
    )
    .fetch_all(pool)
    .await
}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro (Legacy)**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 0e529613dd626d922df62c1d4ad8c386ac84bbd0 and 39779287aaeb8641ecc46b61635df39ae3ec0aff.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `Cargo.lock` is excluded by `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `Cargo.toml` (1 hunks)
* `src/api/handlers.rs` (2 hunks)
* `src/api/mod.rs` (1 hunks)
* `src/db/database.rs` (4 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* src/api/mod.rs

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* Cargo.toml

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>src/db/database.rs (1)</summary><blockquote>

<details>
<summary>src/api/handlers.rs (2)</summary>

* `get_pending_withdrawals` (90-101)
* `create_withdrawal` (69-88)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>src/api/handlers.rs (2)</summary>

`7-10`: **Good job organizing imports for the new withdrawal functionality.**

The imports are well-structured and clearly separate the database functions from the handler implementations with appropriate aliases.

---

`12-17`: **The CreateWithdrawalRequest struct is well-defined.**

The struct has appropriate fields for handling withdrawal requests with clear types.

</details>
<details>
<summary>src/db/database.rs (3)</summary>

`25-45`: **The insert_withdrawal function is well-implemented.**

Good work using the query builder pattern and proper error handling. The function correctly returns the UUID of the newly inserted record.

---

`66-67`: **Return statement improvement in insert_deposit function.**

The simplification of the return statement is cleaner.

---

`78-98`: <details>
<summary>❌ Incorrect review comment</summary>

**Type mismatch in create_withdrawal function.**

You're inserting a `Uuid::new_v4()` value for the `id` field, but the `Withdrawal` struct defines it as `i32`. This will cause runtime errors.

---

🏁 Script executed:

```shell
#!/bin/bash
# Verify the database schema for withdrawals table

# Look for the migration that creates the withdrawals table
fd --type f ".*withdrawal.*" -E "*.rs" | xargs cat
```

Length of output: 828

---



</details>

**Verification: UUID Usage is Correct**

After investigating the associated migration script, the `withdrawals` table defines the `id` column as a UUID (with `id UUID PRIMARY KEY DEFAULT gen_random_uuid()`). This means that using `Uuid::new_v4()` in the `create_withdrawal` function is appropriate. Please ensure that the `Withdrawal` struct’s `id` field is defined as a UUID rather than `i32`. If it’s already updated accordingly, you can safely disregard the original type mismatch concern.



> Likely an incorrect or invalid review comment.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-29T23:00:47Z

Review comments:
diff_hunk: @@ -0,0 +1 @@
+export DATABASE_URL=postgresql://zeroxbridge_owner:npg_DJL5WhK3PlBM@ep-royal-art-a5o74xlv-pooler.us-east-2.aws.neon.tech/zeroxbridge?sslmode=require
path: .env
user: login: JoE11-y
body: remove .env file from upload.

Safety first
created_at: 2025-03-28T14:16:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1 +1,37 @@
+use serde::{Serialize, Deserialize};
path: src/api/database.rs
user: login: JoE11-y
body: Let's move this file to `src/db/` — it helps keep the project structure cleaner and easier to manage.

After moving it, don’t forget to update `src/db/mod.rs` to include the file, like so:

```rust
pub mod database;
```

This keeps the module properly exposed and accessible throughout the project.
created_at: 2025-03-28T14:19:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,53 @@
+use axum::{Json, Extension, http::StatusCode};
+use serde::{Deserialize, Serialize};
+use sqlx::PgPool;
+use sha2::{Sha256, Digest};
+use uuid::Uuid;
+
+use crate::api::database::{insert_withdrawal, Withdrawal};
+
+#[derive(Deserialize)]
+pub struct WithdrawalRequest {
+    pub stark_pub_key: String,
+    pub amount: i64,
+}
+
+#[derive(Serialize)]
+pub struct WithdrawalResponse {
+    pub commitment_hash: String,
+}
+
+pub async fn handle_withdrawal_post(
+    Extension(pool): Extension<PgPool>,
+    Json(payload): Json<WithdrawalRequest>,
+) -> Result<Json<WithdrawalResponse>, (StatusCode, String)> {
+    if payload.amount <= 0 || payload.stark_pub_key.trim().is_empty() {
+        return Err((StatusCode::BAD_REQUEST, "Invalid input".to_string()));
+    }
+
+    // Generate a salted commitment hash using UUID
+    let nonce = Uuid::new_v4();
+    let mut hasher = Sha256::new();
+    hasher.update(format!("{}{}{}", payload.stark_pub_key, payload.amount, nonce));
+    let commitment_hash = format!("{:x}", hasher.finalize());
+
+    insert_withdrawal(&pool, &payload.stark_pub_key, payload.amount, &commitment_hash)
+        .await
+        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
+
+    Ok(Json(WithdrawalResponse { commitment_hash }))
+}
+
+pub async fn handle_get_pending_withdrawals(
+    Extension(pool): Extension<PgPool>,
+) -> Result<Json<Vec<Withdrawal>>, (StatusCode, String)> {
+    let withdrawals = sqlx::query_as!(
+        Withdrawal,
path: src/api/handlers.rs
user: login: JoE11-y
body: Let’s move all raw SQL queries into `src/db/database.rs` for better separation of concerns.

For example:

```rust
pub async fn get_pending_withdrawals(pool: &PgPool) -> Result<Vec<Withdrawal>, sqlx::Error> {
    // SQL query here
}
```

Then update your handler to call this function instead of embedding the SQL directly. 
created_at: 2025-03-28T14:21:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,50 @@
+use std::sync::Arc;
+use axum::{
+    Router,
+    routing::{post, get},
+    Extension,
+};
+use sqlx::PgPool;
+
+use crate::api::handlers::{handle_withdrawal_post, handle_get_pending_withdrawals};
+
+#[derive(Clone)]
+pub struct AppState {
+    pub db: PgPool,
+}
+
+pub fn configure_routes() -> Router {
path: src/api/routes.rs
user: login: JoE11-y
body: You can remove this — it's not doing anything at the moment.  
We already have a `create_router` function that sets up and returns all the necessary routes for the application. No need to duplicate that logic here.
created_at: 2025-03-28T14:23:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,36 +1,66 @@
-use axum::{routing::get, Extension, Router};
-use std::{net::SocketAddr, path::Path, sync::Arc};
+use axum::{routing::get, Router};
+use sqlx::postgres::PgPoolOptions;
+use std::sync::Arc;
+use tower_http::trace::TraceLayer;
+use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
+use dotenvy::dotenv;
+use axum::http::StatusCode;
+use crate::api::routes::configure_routes;
+
+
 
 mod config;
-mod db;
+mod api;
 
-use config::load_config;
-use db::client::DBClient;
+use api::routes::AppState;
 
 #[tokio::main]
 async fn main() {
-    let config = load_config(Some(Path::new("config.toml"))).expect("Failed to load config");
+    
+    dotenv().ok();
path: src/main.rs
user: login: JoE11-y
body: Revert back to using the `db` config setup — it keeps the initialization much cleaner and consistent with the rest of the codebase.

```rust
let config = load_config(Some(Path::new("config.toml"))).expect("Failed to load config");

tracing_subscriber::registry()
    .with(tracing_subscriber::EnvFilter::new(
        std::env::var("RUST_LOG").unwrap_or_else(|_| "info".into()),
    ))
    .with(tracing_subscriber::fmt::layer())
    .init();

let db = DBClient::new(&config)
    .await
    .expect("Failed to connect to DB");

db.run_migrations().await.expect("Failed to run migrations");

let shared_db = Arc::new(db);

let app = Router::new()
    .route("/", get(handler))
    .merge(create_router(shared_db.pool.clone()));
```

created_at: 2025-03-28T14:25:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,66 @@
+use axum::{body::Body, http::{Request, StatusCode}};
+use zero_x_bridge_sequencer::api::{handlers::WithdrawalRequest, routes::{create_test_app}};
path: src/test/withdrawal_api.rs
user: login: JoE11-y
body: did you mean to write

use zeroxbridge_sequencer::api::routes::create_test_app;  

and also move the tests outside the src file

tests/withdrawal_api.rs

then add a lib.rs in src.
created_at: 2025-03-28T14:27:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,66 @@
+use axum::{body::Body, http::{Request, StatusCode}};
+use zero_x_bridge_sequencer::api::{handlers::WithdrawalRequest, routes::{create_test_app}};
path: src/test/withdrawal_api.rs
user: login: OthmanImam
body: Ok Sir, i will make the adjustment as requested.
Thank you.
created_at: 2025-03-28T15:47:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,23 @@
+use axum::routing::get;
+use axum::{Router, extract::State};
+use sqlx::PgPool;
+use std::sync::Arc;
+
+pub fn withdrawal_routes() -> Router {
+    Router::new()
+        .route("/withdrawals", get(get_pending_withdrawals))
+        .route("/withdrawals/create", get(create_withdrawal))
+}
+
+async fn get_pending_withdrawals(
+    State(pool): State<Arc<PgPool>>,
+) -> Result<Json<Vec<Withdrawal>>, (axum::http::StatusCode, String)> {
+    // Your handler logic here
+}
path: src/api/routes.rs
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Empty handler implementation needs to be completed.**

The get_pending_withdrawals handler is just a placeholder without actual implementation. This should be implemented or moved to a handlers module.


To complete this implementation, you should call the appropriate database function to fetch pending withdrawals:

```rust
async fn get_pending_withdrawals(
    State(pool): State<Arc<PgPool>>,
) -> Result<Json<Vec<Withdrawal>>, (axum::http::StatusCode, String)> {
    match crate::api::database::get_pending_withdrawals(&pool).await {
        Ok(withdrawals) => Ok(Json(withdrawals)),
        Err(e) => Err((
            axum::http::StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to get pending withdrawals: {}", e)
        ))
    }
}
```

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-28T21:15:28Z
author_association: NONE
diff_hunk: @@ -0,0 +1,23 @@
+use axum::routing::get;
+use axum::{Router, extract::State};
+use sqlx::PgPool;
+use std::sync::Arc;
+
+pub fn withdrawal_routes() -> Router {
+    Router::new()
+        .route("/withdrawals", get(get_pending_withdrawals))
+        .route("/withdrawals/create", get(create_withdrawal))
+}
+
+async fn get_pending_withdrawals(
+    State(pool): State<Arc<PgPool>>,
+) -> Result<Json<Vec<Withdrawal>>, (axum::http::StatusCode, String)> {
+    // Your handler logic here
+}
+
+async fn create_withdrawal(
+    State(pool): State<Arc<PgPool>>,
+    Json(payload): Json<CreateWithdrawalRequest>,
+) -> Result<Json<Withdrawal>, (axum::http::StatusCode, String)> {
+    // Your handler logic here
+}
path: src/api/routes.rs
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Empty handler implementation needs to be completed.**

The create_withdrawal handler is just a placeholder without actual implementation. This should be implemented or moved to a handlers module.


To complete this implementation, you should:
1. Validate the input
2. Generate commitment hash
3. Call the database function to store the withdrawal request

```rust
async fn create_withdrawal(
    State(pool): State<Arc<PgPool>>,
    Json(payload): Json<CreateWithdrawalRequest>,
) -> Result<Json<Withdrawal>, (axum::http::StatusCode, String)> {
    // Validate input
    if payload.amount <= 0 {
        return Err((
            axum::http::StatusCode::BAD_REQUEST,
            "Amount must be greater than zero".to_string()
        ));
    }
    
    // Generate commitment hash
    let commitment_hash = generate_commitment_hash(&payload.stark_pub_key, payload.amount);
    
    // Store in database
    match crate::api::database::insert_withdrawal(&pool, &payload.stark_pub_key, payload.amount, &commitment_hash).await {
        Ok(withdrawal) => Ok(Json(withdrawal)),
        Err(e) => Err((
            axum::http::StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to create withdrawal: {}", e)
        ))
    }
}
```

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-28T21:15:28Z
author_association: NONE
diff_hunk: @@ -0,0 +1,23 @@
+use axum::routing::get;
+use axum::{Router, extract::State};
+use sqlx::PgPool;
+use std::sync::Arc;
+
+pub fn withdrawal_routes() -> Router {
+    Router::new()
+        .route("/withdrawals", get(get_pending_withdrawals))
+        .route("/withdrawals/create", get(create_withdrawal))
+}
path: src/api/routes.rs
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Endpoint setup needs corrections and missing import.**

There are several issues with the withdrawal routes setup:
1. Missing import for `Json` and other types
2. Incorrect HTTP method for create operation
3. Inconsistency between PR objective and implementation (endpoint paths)


Fix the imports and use appropriate HTTP methods:

```diff
- use axum::routing::get;
- use axum::{Router, extract::State};
+ use axum::routing::{get, post};
+ use axum::{Router, extract::State, Json};
+ use crate::api::models::Withdrawal;
+ use crate::api::handlers::{get_pending_withdrawals, create_withdrawal};
+ use crate::api::models::CreateWithdrawalRequest;

pub fn withdrawal_routes() -> Router {
    Router::new()
        .route("/withdrawals", get(get_pending_withdrawals))
-       .route("/withdrawals/create", get(create_withdrawal))
+       .route("/withdrawals", post(create_withdrawal))
}
```

The PR objective mentions endpoints as `/withdraw`, but the implementation uses `/withdrawals`. Consider aligning these for consistency.


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
use axum::routing::{get, post};
use axum::{Router, extract::State, Json};
use crate::api::models::Withdrawal;
use crate::api::handlers::{get_pending_withdrawals, create_withdrawal};
use crate::api::models::CreateWithdrawalRequest;
use sqlx::PgPool;
use std::sync::Arc;

pub fn withdrawal_routes() -> Router {
    Router::new()
        .route("/withdrawals", get(get_pending_withdrawals))
        .route("/withdrawals", post(create_withdrawal))
}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commits 7a3134d to 9eff8ab
created_at: 2025-03-28T21:15:28Z
author_association: NONE
diff_hunk: @@ -0,0 +1,20 @@
+-- 1️⃣ First, create the ENUM type
+CREATE TYPE withdrawal_status AS ENUM ('pending', 'processed', 'failed');
+
+-- 2️⃣ Then, create the table
+CREATE TABLE IF NOT EXISTS withdrawals (
+    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+    stark_pub_key TEXT NOT NULL,
+    amount TEXT NOT NULL,
+    commitment_hash TEXT NOT NULL,
+    status withdrawal_status NOT NULL DEFAULT 'pending', -- Use ENUM type directly
+    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
+    updated_at TIMESTAMPTZ
+);
path: migrations/20250325082529_create_withdrawals_table.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Table creation is clear, but check type usage for `amount` and `id`.**

Your Rust code references an `id` as a UUID in inserts, while the struct uses `i32` for `id`. Also, the code sometimes treats `amount` as an integer. Verify whether storing amount as TEXT aligns with the rest of the application logic.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-28T21:15:29Z
author_association: NONE
diff_hunk: @@ -0,0 +1,66 @@
+use serde::{Serialize, Deserialize};
+use sqlx::{FromRow, PgPool};
+
+#[derive(Debug, FromRow, Serialize, Deserialize)]
+pub struct Withdrawal {
+    pub id: i32,
+    pub stark_pub_key: String,
+    pub amount: i64,
+    pub commitment_hash: String,
+    pub status: String, // "pending", "processed", etc.
+    pub created_at: chrono::NaiveDateTime,
+}
+
+pub async fn insert_withdrawal(
+    pool: &PgPool,
+    stark_pub_key: &str,
+    amount: i64,
+    commitment_hash: &str,
+) -> Result<i32, sqlx::Error> {
+    let row: (i32,) = sqlx::query_as!(
+        Withdrawal,
+        r#"
+        INSERT INTO withdrawals (stark_pub_key, amount, commitment_hash, status)
+        VALUES ($1, $2, $3, 'pending')
+        RETURNING id
+        "#,
+        stark_pub_key,
+        amount,
+        commitment_hash
+    )
+    .fetch_one(pool)
+    .await?;
+
+    Ok(row.0)
+}
+
+pub async fn get_pending_withdrawals(pool: &PgPool) -> Result<Vec<Withdrawal>, sqlx::Error> {
+    sqlx::query_as!(
+        Withdrawal,
+        r#"SELECT * FROM withdrawals WHERE status = 'pending' ORDER BY created_at DESC"#
+    )
+    .fetch_all(pool)
+    .await
+}
+
+pub async fn create_withdrawal(
+    pool: &PgPool,
+    stark_pub_key: String,
+    amount: String,
+    commitment_hash: String,
+) -> Result<Withdrawal, sqlx::Error> {
+    sqlx::query_as!(
+        Withdrawal,
+        r#"
+        INSERT INTO withdrawals (id, stark_pub_key, amount, commitment_hash, status)
+        VALUES ($1, $2, $3, $4, 'pending')
+        RETURNING *
+        "#,
+        Uuid::new_v4(), 
+        stark_pub_key, 
+        amount, 
+        commitment_hash
+    )
+    .fetch_one(pool)
+    .await
+}
path: src/db/database.rs
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Address type consistency for `amount` and ensure `Uuid` import.**

In `create_withdrawal`, you’re inserting `id` via `Uuid::new_v4()`, but your struct fields and table definitions must consistently match the UUID type and the numeric or text type for `amount`. Also confirm `use uuid::Uuid;` is imported.  

```diff
 use uuid::Uuid;

 pub async fn create_withdrawal(
     pool: &PgPool,
     stark_pub_key: String,
-    amount: String,
+    amount: i64,  // or keep as String and store it as TEXT consistently
     commitment_hash: String,
 ) -> Result<Withdrawal, sqlx::Error> {
     sqlx::query_as!(
         Withdrawal,
         r#"
         INSERT INTO withdrawals (id, stark_pub_key, amount, commitment_hash, status)
         VALUES ($1, $2, $3, $4, 'pending')
         RETURNING *
         "#,
         Uuid::new_v4(), 
         stark_pub_key,
         amount,
         commitment_hash
     )
     .fetch_one(pool)
     .await
 }
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
use uuid::Uuid;

pub async fn create_withdrawal(
    pool: &PgPool,
    stark_pub_key: String,
    amount: i64,  // or keep as String and store it as TEXT consistently
    commitment_hash: String,
) -> Result<Withdrawal, sqlx::Error> {
    sqlx::query_as!(
        Withdrawal,
        r#"
        INSERT INTO withdrawals (id, stark_pub_key, amount, commitment_hash, status)
        VALUES ($1, $2, $3, $4, 'pending')
        RETURNING *
        "#,
        Uuid::new_v4(), 
        stark_pub_key,
        amount,
        commitment_hash
    )
    .fetch_one(pool)
    .await
}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-28T21:15:29Z
author_association: NONE
diff_hunk: @@ -0,0 +1,66 @@
+use serde::{Serialize, Deserialize};
+use sqlx::{FromRow, PgPool};
+
+#[derive(Debug, FromRow, Serialize, Deserialize)]
+pub struct Withdrawal {
+    pub id: i32,
+    pub stark_pub_key: String,
+    pub amount: i64,
+    pub commitment_hash: String,
+    pub status: String, // "pending", "processed", etc.
+    pub created_at: chrono::NaiveDateTime,
+}
+
+pub async fn insert_withdrawal(
+    pool: &PgPool,
+    stark_pub_key: &str,
+    amount: i64,
+    commitment_hash: &str,
+) -> Result<i32, sqlx::Error> {
+    let row: (i32,) = sqlx::query_as!(
+        Withdrawal,
+        r#"
+        INSERT INTO withdrawals (stark_pub_key, amount, commitment_hash, status)
+        VALUES ($1, $2, $3, 'pending')
+        RETURNING id
+        "#,
+        stark_pub_key,
+        amount,
+        commitment_hash
+    )
+    .fetch_one(pool)
+    .await?;
+
+    Ok(row.0)
+}
path: src/db/database.rs
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**`insert_withdrawal` is returning an incompatible type for `id`.**

The table’s `id` column is `UUID`, but here it’s returned as a one-element tuple `(i32,)`. This will not match your schema.  

```diff
 pub async fn insert_withdrawal(
     pool: &PgPool,
     stark_pub_key: &str,
     amount: i64,
     commitment_hash: &str,
 ) -> Result<uuid::Uuid, sqlx::Error> {
-    let row: (i32,) = sqlx::query_as!(
-        Withdrawal,
+    let row = sqlx::query!(
         r#"
         INSERT INTO withdrawals (stark_pub_key, amount, commitment_hash, status)
         VALUES ($1, $2, $3, 'pending')
         RETURNING id
         "#,
         stark_pub_key,
         amount,
         commitment_hash
     )
     .fetch_one(pool)
     .await?;
 
-    Ok(row.0)
+    Ok(row.id)
 }
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
pub async fn insert_withdrawal(
    pool: &PgPool,
    stark_pub_key: &str,
    amount: i64,
    commitment_hash: &str,
) -> Result<uuid::Uuid, sqlx::Error> {
    let row = sqlx::query!(
        r#"
        INSERT INTO withdrawals (stark_pub_key, amount, commitment_hash, status)
        VALUES ($1, $2, $3, 'pending')
        RETURNING id
        "#,
        stark_pub_key,
        amount,
        commitment_hash
    )
    .fetch_one(pool)
    .await?;

    Ok(row.id)
}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commits 7a3134d to 9eff8ab
created_at: 2025-03-28T21:15:29Z
author_association: NONE
diff_hunk: @@ -0,0 +1,66 @@
+use serde::{Serialize, Deserialize};
+use sqlx::{FromRow, PgPool};
+
+#[derive(Debug, FromRow, Serialize, Deserialize)]
+pub struct Withdrawal {
+    pub id: i32,
+    pub stark_pub_key: String,
+    pub amount: i64,
+    pub commitment_hash: String,
+    pub status: String, // "pending", "processed", etc.
+    pub created_at: chrono::NaiveDateTime,
+}
path: src/db/database.rs
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Mismatch between database schema and struct fields.**

The migration defines `id` as `UUID`, but the struct uses `i32`. This will cause runtime errors or type conflicts. Adjust the struct to use a compatible type, for example `Uuid`.  

```diff
 #[derive(Debug, FromRow, Serialize, Deserialize)]
 pub struct Withdrawal {
-    pub id: i32,
+    pub id: uuid::Uuid,
     pub stark_pub_key: String,
-    pub amount: i64,
+    // Decide whether to store as i64 or keep matching the DB's TEXT type
     pub amount: i64,
     pub commitment_hash: String,
     pub status: String,
     pub created_at: chrono::NaiveDateTime,
 }
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
use serde::{Serialize, Deserialize};
use sqlx::{FromRow, PgPool};

#[derive(Debug, FromRow, Serialize, Deserialize)]
pub struct Withdrawal {
    pub id: uuid::Uuid,
    pub stark_pub_key: String,
    // Decide whether to store as i64 or keep matching the DB's TEXT type
    pub amount: i64,
    pub commitment_hash: String,
    pub status: String, // "pending", "processed", etc.
    pub created_at: chrono::NaiveDateTime,
}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-28T21:15:29Z
author_association: NONE
diff_hunk: @@ -27,29 +32,35 @@ async fn main() {
         sync_tvl(l1_contract, l2_contract, &config).await.expect("TVL sync failed");
     });
 
+    tracing_subscriber::registry()
+        .with(tracing_subscriber::EnvFilter::new(
+            std::env::var("RUST_LOG").unwrap_or_else(|_| "info".into()),
+        ))
+        .with(tracing_subscriber::fmt::layer())
+        .init();
 
-    let config = load_config(Some(Path::new("config.toml"))).expect("Failed to load config");
-
-    let db = DBClient::new(&config)
+    let pool = get_db_pool()
         .await
-        .expect("Failed to connect to DB");
+        .expect("Failed to connect to database");
 
-    db.run_migrations().await.expect("Failed to run migrations");
+    let state = Arc::new(pool);
path: src/main.rs
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Missing database migrations**

The new database connection approach doesn't explicitly run migrations, which was present in the previous implementation. This could lead to schema inconsistencies.


```diff
let pool = get_db_pool()
    .await
    .expect("Failed to connect to database");

+ // Run migrations to ensure database schema is up to date
+ sqlx::migrate!("./migrations")
+     .run(&pool)
+     .await
+     .expect("Failed to run migrations");

let state = Arc::new(pool);
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
    let pool = get_db_pool()
        .await
        .expect("Failed to connect to database");

    // Run migrations to ensure database schema is up to date
    sqlx::migrate!("./migrations")
        .run(&pool)
        .await
        .expect("Failed to run migrations");

    let state = Arc::new(pool);
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commits 7a3134d to 9eff8ab
created_at: 2025-03-28T22:50:45Z
author_association: NONE
diff_hunk: @@ -27,29 +32,35 @@ async fn main() {
         sync_tvl(l1_contract, l2_contract, &config).await.expect("TVL sync failed");
     });
 
+    tracing_subscriber::registry()
+        .with(tracing_subscriber::EnvFilter::new(
+            std::env::var("RUST_LOG").unwrap_or_else(|_| "info".into()),
+        ))
+        .with(tracing_subscriber::fmt::layer())
+        .init();
 
-    let config = load_config(Some(Path::new("config.toml"))).expect("Failed to load config");
-
-    let db = DBClient::new(&config)
+    let pool = get_db_pool()
         .await
-        .expect("Failed to connect to DB");
+        .expect("Failed to connect to database");
 
-    db.run_migrations().await.expect("Failed to run migrations");
+    let state = Arc::new(pool);
 
-    let shared_db = Arc::new(db);
+    let app = create_router(state.clone());
 
-    let app = Router::new()
-        .route("/", get(handler))
-        .layer(Extension(shared_db));
+    let addr = "0.0.0.0:3000".parse().unwrap();
+    let server = Server::try_bind(&addr);
 
-    let addr: SocketAddr = "127.0.0.1:3000".parse().unwrap();
-    println!("ZeroXBridge Sequencer listening on {}", addr);
+    println!("🚀 Listening on {}", addr);
 
-    axum::serve(tokio::net::TcpListener::bind(addr).await.unwrap(), app)
+    Server::bind(&addr)
+        .serve(app.into_make_service())
path: src/main.rs
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Duplicate server binding**

There is a duplicate server binding operation. Line 51 creates a server binding but doesn't use it, then lines 55-56 create another binding that's actually used.


```diff
- let addr = "0.0.0.0:3000".parse().unwrap();
- let server = Server::try_bind(&addr);
+ let addr: SocketAddr = "0.0.0.0:3000".parse().unwrap();

println!("🚀 Listening on {}", addr);

Server::bind(&addr)
```


> Committable suggestion skipped: line range outside the PR's diff.

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commits 1e36edc to 0e52961
created_at: 2025-03-28T22:50:45Z
author_association: NONE
diff_hunk: @@ -55,3 +66,37 @@ pub async fn handle_get_pending_deposits(
 
     Ok(Json(deposit))
 }
+
+pub async fn create_withdrawal(
+    Extension(pool): Extension<PgPool>,
+    Json(payload): Json<CreateWithdrawalRequest>,
+) -> Result<Json<Withdrawal>, (StatusCode, String)> {
+    let withdrawal = db_create_withdrawal(
+        &pool,
+        payload.stark_pub_key,
+        payload.amount,
+        payload.commitment_hash,
+    )
+    .await
+    .map_err(|err| {
+        (
+            StatusCode::INTERNAL_SERVER_ERROR,
+            format!("DB Error: {:?}", err),
+        )
+    })?;
+
+    Ok(Json(withdrawal))
+}
path: src/api/handlers.rs
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Add basic input validation for withdrawal creation.**

Currently, no checks exist for negative or zero amounts, nor verification of a non-empty public key. This could lead to invalid or erroneous records. Consider validating the request payload similarly to deposit logic.  

For example:

```diff
+ if payload.amount <= 0 || payload.stark_pub_key.trim().is_empty() {
+     return Err((
+         StatusCode::BAD_REQUEST,
+         "Invalid withdrawal parameters".to_string(),
+     ));
+ }
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
pub async fn create_withdrawal(
    Extension(pool): Extension<PgPool>,
    Json(payload): Json<CreateWithdrawalRequest>,
) -> Result<Json<Withdrawal>, (StatusCode, String)> {
    if payload.amount <= 0 || payload.stark_pub_key.trim().is_empty() {
        return Err((
            StatusCode::BAD_REQUEST,
            "Invalid withdrawal parameters".to_string(),
        ));
    }
    let withdrawal = db_create_withdrawal(
        &pool,
        payload.stark_pub_key,
        payload.amount,
        payload.commitment_hash,
    )
    .await
    .map_err(|err| {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("DB Error: {:?}", err),
        )
    })?;

    Ok(Json(withdrawal))
}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-29T22:21:20Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-03-28T21:11:33Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This update introduces new withdrawal-related functionality. A new environment variable is added for database connection, and configuration files have been updated accordingly. Two migration scripts create a withdrawals table and define its constraints and indexes. New API endpoints for creating and fetching pending withdrawals have been implemented along with corresponding database functions. In addition, logging, dependency updates, and module visibility improvements have been applied. A new test suite validates the withdrawal API’s behavior.

## Changes

| File(s)                                                                                              | Change Summary                                                                                                                                                                                                                                                                                                                                       |
| ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `.env`, `.gitignore`, `Cargo.toml`, `src/config.rs`, `src/lib.rs`, `src/main.rs`                     | Added a new `DATABASE_URL` environment variable; updated `.gitignore` to ignore sensitive files; updated the `axum` dependency from 0.8.1 to 0.8.3; enhanced logging and database pool setup in `main.rs`; made formatting and module visibility adjustments in configuration and library files.                                                 |
| `migrations/…withdrawals_table.sql`, `src/db/database.rs`                                           | Introduced two migration scripts for the withdrawals table (one placeholder and one implementing table creation with ENUM, constraints, and indexes); added a new `Withdrawal` struct and functions to insert and retrieve withdrawal records from the database.                                                                             |
| `src/api/handlers.rs`, `src/api/routes.rs`, `src/api/mod.rs`                                         | Implemented the `CreateWithdrawalRequest` struct along with `create_withdrawal` and `get_pending_withdrawals` handlers; updated API routing in `routes.rs` to include POST and GET endpoints for withdrawals; modified module declarations in `mod.rs`.                                                                                     |
| `tests/test_withdrawal_api.rs`                                                                       | Added a new test suite for the withdrawal API, covering valid and invalid POST requests and the retrieval of pending withdrawals via a GET request.                                                                                                                                                                                               |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant API
    participant DB
    User->>API: POST /withdraw with CreateWithdrawalRequest payload
    API->>DB: Call create_withdrawal (generates commitment hash, sets status "pending")
    DB-->>API: Return newly created withdrawal record
    API-->>User: JSON response containing withdrawal details
```

```mermaid
sequenceDiagram
    participant User
    participant API
    participant DB
    User->>API: GET /withdraw (retrieve pending withdrawals)
    API->>DB: Call get_pending_withdrawals()
    DB-->>API: Return list of pending withdrawals
    API-->>User: JSON response with withdrawal list
```

## Assessment against linked issues

| Objective                                                                       | Addressed | Explanation                                          |
| ------------------------------------------------------------------------------- | --------- | ---------------------------------------------------- |
| Implement Withdrawal Request API Endpoint (POST and GET endpoints) [#2]         | ✅        |                                                    |
| Validate inputs, persist withdrawals with status "pending", and add unit tests [#2] | ✅        |                                                    |

## Poem
> I’m a bunny with code so bright,  
> Hopping through routes with delight,  
> New endpoints bloom like spring flowers,  
> Database leaps with pending powers,  
> With every test, my heart takes flight! 🐇✨

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Explore-Beyond-Innovations/ZeroXBridge_Sequencer&utm_content=10):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: JoE11-y
created_at: 2025-03-29T22:29:17Z
body: I've helped out with the merge conflicts.

I think this is ready to merge, just need to take a look for cleanups etc.
author_association: CONTRIBUTOR