Skip to content

Commit 25b2455

Browse files
committed
refactor: add inject sender middleware
Signed-off-by: Gustavo Inacio <[email protected]>
1 parent 4492685 commit 25b2455

File tree

3 files changed

+110
-3
lines changed

3 files changed

+110
-3
lines changed

crates/service/src/error.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33

44
use alloy::primitives::Address;
55
use anyhow::Error;
6-
use axum::{response::{IntoResponse, Response}, Json};
6+
use axum::{
7+
response::{IntoResponse, Response},
8+
Json,
9+
};
710
use indexer_monitor::EscrowAccountsError;
811
use reqwest::StatusCode;
912
use serde::Serialize;
@@ -13,7 +16,7 @@ use thiserror::Error;
1316
#[derive(Debug, Error)]
1417
pub enum IndexerServiceError {
1518
#[error("Issues with provided receipt: {0}")]
16-
ReceiptError(tap_core::Error),
19+
ReceiptError(#[from] tap_core::Error),
1720
#[error("No attestation signer found for allocation `{0}`")]
1821
NoSignerForAllocation(Address),
1922
#[error("Invalid request body: {0}")]
@@ -31,7 +34,7 @@ pub enum IndexerServiceError {
3134
CouldNotDecodeSigner(tap_core::Error),
3235

3336
#[error("There was an error while accessing escrow account: {0}")]
34-
EscrowAccount(EscrowAccountsError),
37+
EscrowAccount(#[from] EscrowAccountsError),
3538
}
3639

3740
impl IntoResponse for IndexerServiceError {

crates/service/src/middleware.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33

44
mod inject_deployment;
55
mod inject_receipt;
6+
mod inject_sender;
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use alloy::dyn_abi::Eip712Domain;
5+
use axum::{
6+
extract::{Request, State},
7+
middleware::Next,
8+
response::Response,
9+
};
10+
use indexer_monitor::EscrowAccounts;
11+
use tap_core::receipt::SignedReceipt;
12+
use tokio::sync::watch;
13+
14+
use crate::error::IndexerServiceError;
15+
16+
#[derive(Clone)]
17+
pub struct SenderState {
18+
pub domain_separator: Eip712Domain,
19+
pub escrow_accounts: watch::Receiver<EscrowAccounts>,
20+
}
21+
22+
#[derive(Clone)]
23+
pub struct Sender(String);
24+
25+
impl From<Sender> for String {
26+
fn from(value: Sender) -> Self {
27+
value.0
28+
}
29+
}
30+
31+
pub async fn sender_middleware(
32+
State(state): State<SenderState>,
33+
mut request: Request,
34+
next: Next,
35+
) -> Result<Response, IndexerServiceError> {
36+
if let Some(receipt) = request.extensions().get::<SignedReceipt>() {
37+
let signer = receipt.recover_signer(&state.domain_separator)?;
38+
let sender = state
39+
.escrow_accounts
40+
.borrow()
41+
.get_sender_for_signer(&signer)?;
42+
request.extensions_mut().insert(Sender(sender.to_string()));
43+
}
44+
45+
Ok(next.run(request).await)
46+
}
47+
48+
#[cfg(test)]
49+
mod tests {
50+
use crate::middleware::inject_sender::SenderState;
51+
52+
use super::{sender_middleware, Sender};
53+
use alloy::primitives::Address;
54+
use axum::{
55+
body::Body,
56+
http::{Extensions, Request},
57+
middleware::from_fn_with_state,
58+
routing::get,
59+
Router,
60+
};
61+
use indexer_monitor::EscrowAccounts;
62+
use reqwest::StatusCode;
63+
use test_assets::{create_signed_receipt, ESCROW_ACCOUNTS_BALANCES, ESCROW_ACCOUNTS_SENDERS_TO_SIGNERS};
64+
use tokio::sync::watch;
65+
use tower::ServiceExt;
66+
67+
#[tokio::test]
68+
async fn test_sender_middleware() {
69+
let escrow_accounts = watch::channel(EscrowAccounts::new(
70+
ESCROW_ACCOUNTS_BALANCES.to_owned(),
71+
ESCROW_ACCOUNTS_SENDERS_TO_SIGNERS.to_owned(),
72+
))
73+
.1;
74+
let state = SenderState {
75+
domain_separator: test_assets::TAP_EIP712_DOMAIN.clone(),
76+
escrow_accounts,
77+
};
78+
79+
let middleware = from_fn_with_state(state, sender_middleware);
80+
81+
async fn handle(extensions: Extensions) -> Body {
82+
let sender = extensions.get::<Sender>().expect("Should contain sender");
83+
assert_eq!(sender.0, test_assets::TAP_SENDER.1.to_string());
84+
Body::empty()
85+
}
86+
87+
let app = Router::new().route("/", get(handle)).layer(middleware);
88+
89+
let receipt = create_signed_receipt(Address::ZERO, 1, 1, 1).await;
90+
91+
let res = app
92+
.oneshot(
93+
Request::builder()
94+
.uri("/")
95+
.extension(receipt)
96+
.body(Body::empty())
97+
.unwrap(),
98+
)
99+
.await
100+
.unwrap();
101+
assert_eq!(res.status(), StatusCode::OK);
102+
}
103+
}

0 commit comments

Comments
 (0)