walletkit_core/
requests.rs1use world_id_core::requests::{
2 ProofRequest as CoreProofRequest, ProofResponse as CoreProofResponse,
3};
4
5use crate::error::WalletKitError;
6
7#[derive(Debug, Clone, uniffi::Object)]
10pub struct ProofRequest(pub(crate) CoreProofRequest);
11
12#[uniffi::export]
13impl ProofRequest {
14 #[uniffi::constructor]
19 pub fn from_json(json: &str) -> Result<Self, WalletKitError> {
20 let core_request = CoreProofRequest::from_json(json).map_err(|e| {
21 WalletKitError::InvalidInput {
22 attribute: "proof_request".to_string(),
23 reason: format!("invalid proof request json: {e}"),
24 }
25 })?;
26 Ok(Self(core_request))
27 }
28
29 pub fn to_json(&self) -> Result<String, WalletKitError> {
34 serde_json::to_string(&self.0).map_err(|e| WalletKitError::Generic {
35 error: format!("critical unexpected error serializing to json: {e}"),
36 })
37 }
38
39 #[must_use]
41 pub fn id(&self) -> String {
42 self.0.id.clone()
43 }
44
45 #[must_use]
47 pub const fn version(&self) -> u8 {
48 self.0.version as u8
49 }
50}
51
52#[derive(Debug, Clone, uniffi::Object)]
56pub struct ProofResponse(pub CoreProofResponse);
57
58#[uniffi::export]
59impl ProofResponse {
60 pub fn to_json(&self) -> Result<String, WalletKitError> {
65 serde_json::to_string(&self.0).map_err(|e| WalletKitError::Generic {
66 error: format!("critical unexpected error serializing to json: {e}"),
67 })
68 }
69
70 #[must_use]
72 pub fn id(&self) -> String {
73 self.0.id.clone()
74 }
75
76 #[must_use]
78 pub const fn version(&self) -> u8 {
79 self.0.version as u8
80 }
81
82 #[must_use]
84 pub fn error(&self) -> Option<String> {
85 self.0.error.clone()
86 }
87}
88
89impl ProofResponse {
90 #[must_use]
92 pub fn into_inner(self) -> CoreProofResponse {
93 self.0
94 }
95}
96
97impl From<CoreProofRequest> for ProofRequest {
98 fn from(core_request: CoreProofRequest) -> Self {
99 Self(core_request)
100 }
101}
102
103impl From<CoreProofResponse> for ProofResponse {
104 fn from(core_response: CoreProofResponse) -> Self {
105 Self(core_response)
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use alloy::signers::{local::PrivateKeySigner, SignerSync};
112 use alloy_core::primitives::U160;
113 use serde_json::Value;
114 use taceo_oprf::types::OprfKeyId;
115 use world_id_core::{
116 primitives::{rp::RpId, FieldElement},
117 requests::{ProofType, RequestItem, RequestVersion},
118 };
119
120 use super::*;
121
122 fn test_signature() -> alloy::signers::Signature {
123 let signer = PrivateKeySigner::from_bytes(&[1u8; 32].into())
124 .expect("test signer should be valid");
125 signer
126 .sign_message_sync(b"test")
127 .expect("test signature should sign")
128 }
129
130 fn base_core_request(proof_type: ProofType) -> CoreProofRequest {
131 CoreProofRequest {
132 id: "test_request".to_string(),
133 version: RequestVersion::V1,
134 proof_type,
135 created_at: 1_700_000_000,
136 expires_at: 1_700_000_300,
137 rp_id: RpId::new(1),
138 oprf_key_id: OprfKeyId::new(U160::from(1)),
139 session_id: None,
140 action: Some(FieldElement::from(1u64)),
141 signature: test_signature(),
142 nonce: FieldElement::from(2u64),
143 requests: vec![RequestItem {
144 identifier: "credential".to_string(),
145 issuer_schema_id: 1,
146 signal: None,
147 genesis_issued_at_min: None,
148 expires_at_min: None,
149 }],
150 constraints: None,
151 }
152 }
153
154 #[test]
155 fn from_json_defaults_missing_proof_type_to_uniqueness() {
156 let core_request = base_core_request(ProofType::Uniqueness);
157 let mut value =
158 serde_json::to_value(core_request).expect("request should serialize");
159 value
160 .as_object_mut()
161 .expect("request should be an object")
162 .remove("proof_type");
163
164 let json =
165 serde_json::to_string(&value).expect("request json should serialize");
166 let request = ProofRequest::from_json(&json).expect("request should parse");
167
168 assert_eq!(request.0.proof_type, ProofType::Uniqueness);
169 }
170
171 #[test]
172 fn from_json_rejects_invalid_proof_type_fields() {
173 let mut value = serde_json::to_value(base_core_request(ProofType::Uniqueness))
174 .expect("request should serialize");
175 let object = value.as_object_mut().expect("request should be an object");
176 object.insert(
177 "proof_type".to_string(),
178 Value::String("session".to_string()),
179 );
180 object.remove("action");
181
182 let json =
183 serde_json::to_string(&value).expect("request json should serialize");
184 let error = ProofRequest::from_json(&json)
185 .expect_err("session request needs session_id");
186
187 match error {
188 WalletKitError::InvalidInput { attribute, reason } => {
189 assert_eq!(attribute, "proof_request");
190 assert!(reason.contains("session_id"));
191 }
192 other => panic!("expected invalid input error, got {other:?}"),
193 }
194 }
195}