Skip to main content

world_id_authenticator/
init.rs

1use alloy::primitives::Address;
2use ark_serialize::CanonicalSerialize;
3use ruint::aliases::U256;
4use world_id_primitives::{AuthenticatorPublicKeySet, PrimitiveError, Signer};
5
6use crate::{
7    api_types::{
8        CreateAccountRequest, GatewayRequestId, GatewayRequestState, GatewayStatusResponse,
9    },
10    error::AuthenticatorError,
11    service_client::ServiceClient,
12};
13
14pub use world_id_primitives::Config;
15
16/// Represents an account in the process of being initialized,
17/// i.e. it is not yet registered in the `WorldIDRegistry` contract.
18pub struct InitializingAuthenticator {
19    request_id: GatewayRequestId,
20    gateway_client: ServiceClient,
21    config: Config,
22}
23
24impl InitializingAuthenticator {
25    /// Returns the gateway request ID for this pending account creation.
26    #[must_use]
27    pub fn request_id(&self) -> &GatewayRequestId {
28        &self.request_id
29    }
30
31    /// Creates a new World ID account by adding it to the registry using the gateway.
32    ///
33    /// # Errors
34    /// - See `Signer::from_seed_bytes` for additional error details.
35    /// - Will error if the gateway rejects the request or a network error occurs.
36    pub(crate) async fn new(
37        seed: &[u8],
38        config: Config,
39        recovery_address: Option<Address>,
40        gateway_client: ServiceClient,
41    ) -> Result<Self, AuthenticatorError> {
42        let signer = Signer::from_seed_bytes(seed)?;
43
44        let mut key_set = AuthenticatorPublicKeySet::default();
45        key_set.try_push(signer.offchain_signer_pubkey())?;
46        let leaf_hash = key_set.leaf_hash();
47
48        let offchain_pubkey_compressed = {
49            let pk = signer.offchain_signer_pubkey().pk;
50            let mut compressed_bytes = Vec::new();
51            pk.serialize_compressed(&mut compressed_bytes)
52                .map_err(|e| PrimitiveError::Serialization(e.to_string()))?;
53            U256::from_le_slice(&compressed_bytes)
54        };
55
56        let req = CreateAccountRequest {
57            recovery_address,
58            authenticator_addresses: vec![signer.onchain_signer_address()],
59            authenticator_pubkeys: vec![offchain_pubkey_compressed],
60            offchain_signer_commitment: leaf_hash.into(),
61        };
62
63        let body: GatewayStatusResponse = gateway_client
64            .post_json(config.gateway_url(), "/create-account", &req)
65            .await?;
66        Ok(Self {
67            request_id: body.request_id,
68            gateway_client,
69            config,
70        })
71    }
72
73    /// Poll the status of the World ID creation request.
74    ///
75    /// # Errors
76    /// - Will error if the network request fails.
77    /// - Will error if the gateway returns an error response.
78    pub async fn poll_status(&self) -> Result<GatewayRequestState, AuthenticatorError> {
79        let path = format!("/status/{}", self.request_id);
80        let body: GatewayStatusResponse = self
81            .gateway_client
82            .get_json(self.config.gateway_url(), &path)
83            .await?;
84        Ok(body.status)
85    }
86}