Skip to main content

walletkit_core/
credential.rs

1//! FFI-friendly wrapper around [`CoreCredential`].
2
3use std::ops::Deref;
4
5use world_id_core::Credential as CoreCredential;
6
7use crate::error::WalletKitError;
8use crate::FieldElement;
9
10/// A wrapper around [`CoreCredential`] to enable FFI interoperability.
11///
12/// Encapsulates the credential and exposes accessors for fields that FFI
13/// callers need.
14#[derive(Debug, Clone, uniffi::Object)]
15pub struct Credential(CoreCredential);
16
17#[uniffi::export]
18impl Credential {
19    /// Deserializes a `Credential` from a JSON byte blob.
20    ///
21    /// # Errors
22    ///
23    /// Returns an error if the bytes cannot be deserialized.
24    #[uniffi::constructor]
25    #[allow(clippy::needless_pass_by_value)]
26    pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, WalletKitError> {
27        let credential: CoreCredential =
28            serde_json::from_slice(&bytes).map_err(|e| {
29                WalletKitError::InvalidInput {
30                    attribute: "credential_bytes".to_string(),
31                    reason: format!("Failed to deserialize credential: {e}"),
32                }
33            })?;
34        Ok(Self(credential))
35    }
36
37    /// Returns the credential's `sub` field element.
38    #[must_use]
39    pub fn sub(&self) -> FieldElement {
40        self.0.sub.into()
41    }
42
43    /// Returns the credential's issuer schema ID.
44    #[must_use]
45    pub const fn issuer_schema_id(&self) -> u64 {
46        self.0.issuer_schema_id
47    }
48}
49
50impl Credential {
51    /// Serializes the credential to a JSON byte blob for storage.
52    ///
53    /// # Errors
54    ///
55    /// Returns an error if serialization fails.
56    pub fn to_bytes(&self) -> Result<Vec<u8>, WalletKitError> {
57        serde_json::to_vec(&self.0).map_err(|e| WalletKitError::SerializationError {
58            error: format!("Failed to serialize credential: {e}"),
59        })
60    }
61
62    /// Returns the credential's `genesis_issued_at` timestamp.
63    #[must_use]
64    pub const fn genesis_issued_at(&self) -> u64 {
65        self.0.genesis_issued_at
66    }
67}
68
69impl From<CoreCredential> for Credential {
70    fn from(val: CoreCredential) -> Self {
71        Self(val)
72    }
73}
74
75impl From<Credential> for CoreCredential {
76    fn from(val: Credential) -> Self {
77        val.0
78    }
79}
80
81impl Deref for Credential {
82    type Target = CoreCredential;
83
84    fn deref(&self) -> &Self::Target {
85        &self.0
86    }
87}