From 69bc72ff4c319df389ce5f27fafc990997fa5f5f Mon Sep 17 00:00:00 2001 From: kilianglas Date: Wed, 15 Apr 2026 18:23:43 +0200 Subject: [PATCH 1/5] feat: migrate walletkit-core from Config to AuthenticatorConfig for OHTTP support --- walletkit-core/src/authenticator/mod.rs | 25 +++++++-------- walletkit-core/src/defaults.rs | 41 ++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/walletkit-core/src/authenticator/mod.rs b/walletkit-core/src/authenticator/mod.rs index 0e2a6ae7e..3dbc6617f 100644 --- a/walletkit-core/src/authenticator/mod.rs +++ b/walletkit-core/src/authenticator/mod.rs @@ -10,8 +10,8 @@ use ruint_uniffi::Uint256; use std::sync::Arc; use world_id_core::{ api_types::{GatewayErrorCode, GatewayRequestState}, - primitives::{authenticator::AuthenticatorPublicKeySet, Config}, - Authenticator as CoreAuthenticator, Credential as CoreCredential, + primitives::authenticator::AuthenticatorPublicKeySet, + Authenticator as CoreAuthenticator, AuthenticatorConfig, Credential as CoreCredential, InitializingAuthenticator as CoreInitializingAuthenticator, OnchainKeyRepresentable, Signer, }; @@ -342,7 +342,7 @@ impl Authenticator { environment: &Environment, region: Option, ) -> Result { - let config = Config::from_environment(environment, rpc_url, region)?; + let config = AuthenticatorConfig::from_environment(environment, rpc_url, region)?; let authenticator = CoreAuthenticator::init(seed, config).await?; let (query_material, nullifier_material) = load_embedded_materials()?; let authenticator = @@ -362,7 +362,7 @@ impl Authenticator { #[uniffi::constructor] pub async fn init(seed: &[u8], config: &str) -> Result { let config = - Config::from_json(config).map_err(|_| WalletKitError::InvalidInput { + AuthenticatorConfig::from_json(config).map_err(|_| WalletKitError::InvalidInput { attribute: "config".to_string(), reason: "Invalid config".to_string(), })?; @@ -396,8 +396,8 @@ impl Authenticator { paths: &StoragePaths, store: Arc, ) -> Result { - let config = Config::from_environment(environment, rpc_url, region)?; - let authenticator = CoreAuthenticator::init(seed, config.into()).await?; + let config = AuthenticatorConfig::from_environment(environment, rpc_url, region)?; + let authenticator = CoreAuthenticator::init(seed, config).await?; let (query_material, nullifier_material) = load_cached_materials(paths)?; let authenticator = authenticator.with_proof_materials(query_material, nullifier_material); @@ -423,11 +423,11 @@ impl Authenticator { store: Arc, ) -> Result { let config = - Config::from_json(config).map_err(|_| WalletKitError::InvalidInput { + AuthenticatorConfig::from_json(config).map_err(|_| WalletKitError::InvalidInput { attribute: "config".to_string(), reason: "Invalid config".to_string(), })?; - let authenticator = CoreAuthenticator::init(seed, config.into()).await?; + let authenticator = CoreAuthenticator::init(seed, config).await?; let (query_material, nullifier_material) = load_cached_materials(paths)?; let authenticator = authenticator.with_proof_materials(query_material, nullifier_material); @@ -615,10 +615,10 @@ impl InitializingAuthenticator { let recovery_address = Address::parse_from_ffi_optional(recovery_address, "recovery_address")?; - let config = Config::from_environment(environment, rpc_url, region)?; + let config = AuthenticatorConfig::from_environment(environment, rpc_url, region)?; let initializing_authenticator = - CoreAuthenticator::register(seed, config.into(), recovery_address).await?; + CoreAuthenticator::register(seed, config, recovery_address).await?; Ok(Self(initializing_authenticator)) } @@ -645,13 +645,13 @@ impl InitializingAuthenticator { Address::parse_from_ffi_optional(recovery_address, "recovery_address")?; let config = - Config::from_json(config).map_err(|_| WalletKitError::InvalidInput { + AuthenticatorConfig::from_json(config).map_err(|_| WalletKitError::InvalidInput { attribute: "config".to_string(), reason: "Invalid config".to_string(), })?; let initializing_authenticator = - CoreAuthenticator::register(seed, config.into(), recovery_address).await?; + CoreAuthenticator::register(seed, config, recovery_address).await?; Ok(Self(initializing_authenticator)) } @@ -815,6 +815,7 @@ mod storage_tests { cleanup_test_storage, temp_root_path, InMemoryStorageProvider, }; use alloy::primitives::address; + use world_id_core::primitives::Config; async fn init_test_authenticator( seed: &[u8], diff --git a/walletkit-core/src/defaults.rs b/walletkit-core/src/defaults.rs index d1a7aad27..2746378ab 100644 --- a/walletkit-core/src/defaults.rs +++ b/walletkit-core/src/defaults.rs @@ -1,5 +1,5 @@ use alloy_primitives::{address, Address}; -use world_id_core::primitives::Config; +use world_id_core::{primitives::Config, AuthenticatorConfig, OhttpClientConfig}; use crate::{error::WalletKitError, Environment, Region}; @@ -66,6 +66,45 @@ pub trait DefaultConfig { Self: Sized; } +fn ohttp_relay_url(region: Region, environment: &Environment) -> String { + let domain = match environment { + Environment::Staging => "worldcoin.dev", + Environment::Production => "world.org", + }; + format!("https://ohttp-relay.{region}.id-infra.{domain}/gateway") +} + +// TODO: replace with real base64-encoded HPKE key configs +const OHTTP_KEY_CONFIG_STAGING: &str = "TODO"; +const OHTTP_KEY_CONFIG_PRODUCTION: &str = "TODO"; + +impl DefaultConfig for AuthenticatorConfig { + fn from_environment( + environment: &Environment, + rpc_url: Option, + region: Option, + ) -> Result { + let region = region.unwrap_or_default(); + let config = Config::from_environment(environment, rpc_url, Some(region))?; + + let key_config_base64 = match environment { + Environment::Staging => OHTTP_KEY_CONFIG_STAGING, + Environment::Production => OHTTP_KEY_CONFIG_PRODUCTION, + }; + let relay_url = ohttp_relay_url(region, environment); + let ohttp = Some(OhttpClientConfig::new( + relay_url, + key_config_base64.to_string(), + )); + + Ok(Self { + config, + ohttp_indexer: ohttp.clone(), + ohttp_gateway: ohttp, + }) + } +} + impl DefaultConfig for Config { fn from_environment( environment: &Environment, From fd1f367700999e61ae6802cf8e53a703acd76077 Mon Sep 17 00:00:00 2001 From: kilianglas Date: Wed, 15 Apr 2026 18:32:12 +0200 Subject: [PATCH 2/5] fix: use correct Cloudflare privacy gateway relay URLs --- walletkit-core/src/defaults.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/walletkit-core/src/defaults.rs b/walletkit-core/src/defaults.rs index 2746378ab..08e5b9c85 100644 --- a/walletkit-core/src/defaults.rs +++ b/walletkit-core/src/defaults.rs @@ -67,11 +67,11 @@ pub trait DefaultConfig { } fn ohttp_relay_url(region: Region, environment: &Environment) -> String { - let domain = match environment { - Environment::Staging => "worldcoin.dev", - Environment::Production => "world.org", + let path = match environment { + Environment::Staging => format!("{region}-world-id-stage"), + Environment::Production => format!("{region}-world-id"), }; - format!("https://ohttp-relay.{region}.id-infra.{domain}/gateway") + format!("https://privacy-gateway.cloudflare.com/{path}") } // TODO: replace with real base64-encoded HPKE key configs From f1cc3fb105f29cdeeba78e76ce75c3e1cc1792dd Mon Sep 17 00:00:00 2001 From: kilianglas Date: Wed, 15 Apr 2026 18:37:31 +0200 Subject: [PATCH 3/5] feat: map OhttpRelayError to NetworkError for consistent error handling --- walletkit-core/src/error.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/walletkit-core/src/error.rs b/walletkit-core/src/error.rs index e32c412cd..049a44b43 100644 --- a/walletkit-core/src/error.rs +++ b/walletkit-core/src/error.rs @@ -227,6 +227,12 @@ impl From for WalletKitError { } AuthenticatorError::SessionIdMismatch => Self::SessionIdMismatch, + AuthenticatorError::OhttpRelayError { status, body } => Self::NetworkError { + url: "ohttp_relay".to_string(), + error: body, + status: Some(status.as_u16()), + }, + _ => Self::AuthenticatorError { error: error.to_string(), }, From 615eb35f5f87f840377f74fa66d28427fffad586 Mon Sep 17 00:00:00 2001 From: kilianglas Date: Wed, 15 Apr 2026 18:56:11 +0200 Subject: [PATCH 4/5] feat: add ohttp error variant --- walletkit-core/src/error.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/walletkit-core/src/error.rs b/walletkit-core/src/error.rs index 049a44b43..3428085f0 100644 --- a/walletkit-core/src/error.rs +++ b/walletkit-core/src/error.rs @@ -140,6 +140,13 @@ pub enum WalletKitError { /// The error code from the NFC service (e.g. `document_expired`) error_code: String, }, + + /// An error occurred in the OHTTP privacy layer (relay, encapsulation, or framing). + #[error("ohttp_error: {error}")] + OhttpError { + /// The error message from the OHTTP layer + error: String, + }, } impl From for WalletKitError { @@ -227,10 +234,11 @@ impl From for WalletKitError { } AuthenticatorError::SessionIdMismatch => Self::SessionIdMismatch, - AuthenticatorError::OhttpRelayError { status, body } => Self::NetworkError { - url: "ohttp_relay".to_string(), - error: body, - status: Some(status.as_u16()), + AuthenticatorError::OhttpEncapsulationError(_) + | AuthenticatorError::BhttpError(_) + | AuthenticatorError::OhttpRelayError { .. } + | AuthenticatorError::InvalidServiceResponse(_) => Self::OhttpError { + error: error.to_string(), }, _ => Self::AuthenticatorError { From 796a5a1eca27b423440663ac0ffd58fe9befb2f6 Mon Sep 17 00:00:00 2001 From: kilianglas Date: Wed, 15 Apr 2026 19:00:25 +0200 Subject: [PATCH 5/5] fix: apply cargo fmt formatting --- walletkit-core/src/authenticator/mod.rs | 33 +++++++++++++++---------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/walletkit-core/src/authenticator/mod.rs b/walletkit-core/src/authenticator/mod.rs index 3dbc6617f..3a71445c6 100644 --- a/walletkit-core/src/authenticator/mod.rs +++ b/walletkit-core/src/authenticator/mod.rs @@ -11,7 +11,8 @@ use std::sync::Arc; use world_id_core::{ api_types::{GatewayErrorCode, GatewayRequestState}, primitives::authenticator::AuthenticatorPublicKeySet, - Authenticator as CoreAuthenticator, AuthenticatorConfig, Credential as CoreCredential, + Authenticator as CoreAuthenticator, AuthenticatorConfig, + Credential as CoreCredential, InitializingAuthenticator as CoreInitializingAuthenticator, OnchainKeyRepresentable, Signer, }; @@ -342,7 +343,8 @@ impl Authenticator { environment: &Environment, region: Option, ) -> Result { - let config = AuthenticatorConfig::from_environment(environment, rpc_url, region)?; + let config = + AuthenticatorConfig::from_environment(environment, rpc_url, region)?; let authenticator = CoreAuthenticator::init(seed, config).await?; let (query_material, nullifier_material) = load_embedded_materials()?; let authenticator = @@ -361,11 +363,12 @@ impl Authenticator { /// Will error if the provided seed is not valid or if the config is not valid. #[uniffi::constructor] pub async fn init(seed: &[u8], config: &str) -> Result { - let config = - AuthenticatorConfig::from_json(config).map_err(|_| WalletKitError::InvalidInput { + let config = AuthenticatorConfig::from_json(config).map_err(|_| { + WalletKitError::InvalidInput { attribute: "config".to_string(), reason: "Invalid config".to_string(), - })?; + } + })?; let authenticator = CoreAuthenticator::init(seed, config).await?; let (query_material, nullifier_material) = load_embedded_materials()?; let authenticator = @@ -396,7 +399,8 @@ impl Authenticator { paths: &StoragePaths, store: Arc, ) -> Result { - let config = AuthenticatorConfig::from_environment(environment, rpc_url, region)?; + let config = + AuthenticatorConfig::from_environment(environment, rpc_url, region)?; let authenticator = CoreAuthenticator::init(seed, config).await?; let (query_material, nullifier_material) = load_cached_materials(paths)?; let authenticator = @@ -422,11 +426,12 @@ impl Authenticator { paths: &StoragePaths, store: Arc, ) -> Result { - let config = - AuthenticatorConfig::from_json(config).map_err(|_| WalletKitError::InvalidInput { + let config = AuthenticatorConfig::from_json(config).map_err(|_| { + WalletKitError::InvalidInput { attribute: "config".to_string(), reason: "Invalid config".to_string(), - })?; + } + })?; let authenticator = CoreAuthenticator::init(seed, config).await?; let (query_material, nullifier_material) = load_cached_materials(paths)?; let authenticator = @@ -615,7 +620,8 @@ impl InitializingAuthenticator { let recovery_address = Address::parse_from_ffi_optional(recovery_address, "recovery_address")?; - let config = AuthenticatorConfig::from_environment(environment, rpc_url, region)?; + let config = + AuthenticatorConfig::from_environment(environment, rpc_url, region)?; let initializing_authenticator = CoreAuthenticator::register(seed, config, recovery_address).await?; @@ -644,11 +650,12 @@ impl InitializingAuthenticator { let recovery_address = Address::parse_from_ffi_optional(recovery_address, "recovery_address")?; - let config = - AuthenticatorConfig::from_json(config).map_err(|_| WalletKitError::InvalidInput { + let config = AuthenticatorConfig::from_json(config).map_err(|_| { + WalletKitError::InvalidInput { attribute: "config".to_string(), reason: "Invalid config".to_string(), - })?; + } + })?; let initializing_authenticator = CoreAuthenticator::register(seed, config, recovery_address).await?;