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    /// Returns the credential's expiration timestamp (unix seconds).
50    #[must_use]
51    pub const fn expires_at(&self) -> u64 {
52        self.0.expires_at
53    }
54
55    /// Returns the credential's `associated_data_commitment` field element.
56    ///
57    /// The commitment scheme is issuer-defined.
58    #[must_use]
59    pub fn associated_data_commitment(&self) -> FieldElement {
60        self.0.associated_data_commitment.into()
61    }
62}
63
64impl Credential {
65    /// Serializes the credential to a JSON byte blob for storage.
66    ///
67    /// # Errors
68    ///
69    /// Returns an error if serialization fails.
70    pub fn to_bytes(&self) -> Result<Vec<u8>, WalletKitError> {
71        serde_json::to_vec(&self.0).map_err(|e| WalletKitError::SerializationError {
72            error: format!("Failed to serialize credential: {e}"),
73        })
74    }
75
76    /// Returns the credential's `genesis_issued_at` timestamp.
77    #[must_use]
78    pub const fn genesis_issued_at(&self) -> u64 {
79        self.0.genesis_issued_at
80    }
81}
82
83impl From<CoreCredential> for Credential {
84    fn from(val: CoreCredential) -> Self {
85        Self(val)
86    }
87}
88
89impl From<Credential> for CoreCredential {
90    fn from(val: Credential) -> Self {
91        val.0
92    }
93}
94
95impl Deref for Credential {
96    type Target = CoreCredential;
97
98    fn deref(&self) -> &Self::Target {
99        &self.0
100    }
101}