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 world_id_core::{
115 primitives::{rp::RpId, FieldElement, OprfKeyId, SessionRef},
116 requests::{ProofType, RequestItem, RequestVersion},
117 };
118
119 use super::*;
120
121 fn test_signature() -> alloy::signers::Signature {
122 let signer = PrivateKeySigner::from_bytes(&[1u8; 32].into())
123 .expect("test signer should be valid");
124 signer
125 .sign_message_sync(b"test")
126 .expect("test signature should sign")
127 }
128
129 fn base_core_request(proof_type: ProofType) -> CoreProofRequest {
130 CoreProofRequest {
131 id: "test_request".to_string(),
132 version: RequestVersion::V1,
133 proof_type,
134 created_at: 1_700_000_000,
135 expires_at: 1_700_000_300,
136 rp_id: RpId::new(1),
137 oprf_key_id: OprfKeyId::new(U160::from(1)),
138 session_id: SessionRef::None,
139 action: Some(FieldElement::from(1u64)),
140 signature: test_signature(),
141 nonce: FieldElement::from(2u64),
142 requests: vec![RequestItem {
143 identifier: "credential".to_string(),
144 issuer_schema_id: 1,
145 signal: None,
146 genesis_issued_at_min: None,
147 expires_at_min: None,
148 }],
149 constraints: None,
150 }
151 }
152
153 #[test]
154 fn from_json_defaults_missing_proof_type_to_uniqueness() {
155 let core_request = base_core_request(ProofType::Uniqueness);
156 let mut value =
157 serde_json::to_value(core_request).expect("request should serialize");
158 value
159 .as_object_mut()
160 .expect("request should be an object")
161 .remove("proof_type");
162
163 let json =
164 serde_json::to_string(&value).expect("request json should serialize");
165 let request = ProofRequest::from_json(&json).expect("request should parse");
166
167 assert_eq!(request.0.proof_type, ProofType::Uniqueness);
168 }
169
170 #[test]
171 fn from_json_rejects_invalid_proof_type_fields() {
172 let mut value = serde_json::to_value(base_core_request(ProofType::Uniqueness))
173 .expect("request should serialize");
174 let object = value.as_object_mut().expect("request should be an object");
175 object.insert(
176 "proof_type".to_string(),
177 Value::String("session".to_string()),
178 );
179 object.remove("action");
180
181 let json =
182 serde_json::to_string(&value).expect("request json should serialize");
183 let error = ProofRequest::from_json(&json)
184 .expect_err("session request needs session_id");
185
186 match error {
187 WalletKitError::InvalidInput { attribute, reason } => {
188 assert_eq!(attribute, "proof_request");
189 assert!(reason.contains("session_id"));
190 }
191 other => panic!("expected invalid input error, got {other:?}"),
192 }
193 }
194}