Skip to content

Commit de72b50

Browse files
SIWE routes
1 parent f70f86c commit de72b50

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed

src/routes/siwe.rs

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
use crate::{database::types::RELATIONAL_DATABASE, eth_rpc::types::ETHEREUM_ENDPOINT};
2+
use alloy::{primitives::Address, providers::ProviderBuilder};
3+
use axum::{
4+
extract::{Extension, Json},
5+
http::StatusCode,
6+
response::IntoResponse,
7+
};
8+
use jwt_simple::claims::JWTClaims;
9+
use serde::{Deserialize, Serialize};
10+
use siwe::{Message, VerificationError, VerificationOpts, generate_nonce};
11+
use sqlx::prelude::FromRow;
12+
use thiserror::Error;
13+
use time::OffsetDateTime;
14+
15+
use super::types::Claims;
16+
17+
#[derive(Debug, Serialize, Deserialize)]
18+
pub struct Siwe {
19+
message: String,
20+
signature: Vec<u8>,
21+
}
22+
23+
#[derive(FromRow)]
24+
pub struct Nonce {
25+
nonce: Option<String>,
26+
}
27+
28+
pub async fn siwe_add_wallet(
29+
Extension(jwt): Extension<JWTClaims<Claims>>,
30+
Json(payload): Json<Siwe>,
31+
) -> Result<impl IntoResponse, SiweError> {
32+
let msg: Message = payload.message.parse().unwrap();
33+
34+
let nonce = sqlx::query_as!(
35+
Nonce,
36+
"SELECT nonce FROM Customers where email = $1",
37+
jwt.custom.email,
38+
)
39+
.fetch_one(RELATIONAL_DATABASE.get().unwrap())
40+
.await?
41+
.nonce
42+
.ok_or_else(|| SiweError::IncorrectNonce)?;
43+
44+
let rpc = ProviderBuilder::new().on_http(ETHEREUM_ENDPOINT[0].as_str().parse().unwrap());
45+
46+
let verification_opts = VerificationOpts {
47+
domain: Some("Developer DAO Cloud".parse().unwrap()),
48+
nonce: Some(nonce),
49+
timestamp: Some(OffsetDateTime::now_utc()),
50+
rpc_provider: Some(rpc),
51+
};
52+
53+
msg.verify(&payload.signature, &verification_opts).await?;
54+
55+
let address = Address::from(msg.address).to_string();
56+
57+
sqlx::query!(
58+
"UPDATE Customers SET wallet = $1 where email = $2",
59+
address,
60+
jwt.custom.email
61+
)
62+
.execute(RELATIONAL_DATABASE.get().unwrap())
63+
.await?;
64+
65+
Ok((StatusCode::OK, address).into_response())
66+
}
67+
68+
pub async fn get_siwe_nonce(
69+
Extension(jwt): Extension<JWTClaims<Claims>>,
70+
) -> Result<impl IntoResponse, SiweError> {
71+
let nonce = generate_nonce();
72+
sqlx::query!(
73+
"UPDATE Customers SET nonce = $1 where email = $2",
74+
nonce,
75+
jwt.custom.email
76+
)
77+
.execute(RELATIONAL_DATABASE.get().unwrap())
78+
.await?;
79+
Ok((StatusCode::OK, nonce).into_response())
80+
}
81+
82+
#[derive(Debug, Error)]
83+
pub enum SiweError {
84+
#[error(transparent)]
85+
VerificationFailed(#[from] VerificationError),
86+
#[error("Incorrect siwe nonce for user")]
87+
IncorrectNonce,
88+
#[error("An error ocurred while querying the database")]
89+
QueryError(#[from] sqlx::Error),
90+
}
91+
92+
impl IntoResponse for SiweError {
93+
fn into_response(self) -> axum::response::Response {
94+
(
95+
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
96+
self.to_string(),
97+
)
98+
.into_response()
99+
}
100+
}

0 commit comments

Comments
 (0)