mod common;
use common::{authed_client, authenticate, client};
#[tokio::test]
#[ignore = "requires running API server"]
async fn auth_flow_and_profile() {
let (token, address, _signer) = authenticate().await;
let authed = authed_client(&token);
let profile = authed.get_user_profile().await.unwrap().into_inner();
let profile_addr = profile.address.unwrap();
assert_eq!(profile_addr.to_lowercase(), address.to_lowercase());
}
#[tokio::test]
#[ignore = "requires running API server"]
async fn refresh_token_rotates_access_token() {
let signer = alloy::signers::local::PrivateKeySigner::random();
let address = format!("{:?}", signer.address());
let c = client();
let challenge = c
.create_challenge(&monaco_sdk::types::ChallengeRequest {
address: address.parse().unwrap(),
chain_id: None,
client_id: None,
})
.await
.unwrap()
.into_inner();
let message = challenge.message.unwrap();
let nonce = challenge.nonce.unwrap();
let signature = alloy::signers::Signer::sign_message(&signer, message.as_bytes())
.await
.unwrap();
let sig_hex = format!("0x{}", alloy::hex::encode(signature.as_bytes()));
let verify = c
.verify_signature(&monaco_sdk::types::VerifyRequest {
address: address.parse().unwrap(),
chain_id: None,
client_id: None,
nonce: nonce.parse().unwrap(),
signature: sig_hex.parse().unwrap(),
})
.await
.unwrap()
.into_inner();
let refresh_token = verify
.refresh_token
.expect("verify should return a refresh_token");
let original_access = verify.access_token.clone().unwrap();
let refreshed = c
.refresh_token(&monaco_sdk::types::RefreshRequest { refresh_token })
.await
.unwrap()
.into_inner();
let new_access = refreshed
.access_token
.expect("refresh should return a new access_token");
assert!(
!new_access.is_empty(),
"refresh returned empty access_token"
);
assert_ne!(
new_access, original_access,
"refresh must rotate the access token — returning the same JWT on refresh would be a security regression"
);
let authed = authed_client(&new_access);
let profile = authed.get_user_profile().await.unwrap().into_inner();
assert_eq!(
profile.address.unwrap().to_lowercase(),
address.to_lowercase(),
"refreshed access_token should authenticate as the original wallet"
);
}
#[tokio::test]
#[ignore = "requires running API server"]
async fn unauthenticated_profile_call_is_rejected() {
let resp = client().get_user_profile().await;
let Err(err) = resp else {
panic!("expected 401 from get_user_profile without auth, got Ok");
};
match err {
monaco_sdk::Error::ErrorResponse(r) => {
assert_eq!(r.status().as_u16(), 401, "expected HTTP 401, got {r:?}");
}
other => panic!("expected ErrorResponse(401), got {other:?}"),
}
}