Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Generate a proof

A relying party asks for a World ID proof by sending a proof request. This page shows how a WalletKit app answers it with a registered account. To register an account and store credentials first, see Accounts and credentials.

Before you begin

Answer a proof request

The following Rust function opens the account, binds its storage, and answers a proof request. The Swift, Kotlin, and browser APIs take the same steps with the same names in their own casing.

#![allow(unused)]
fn main() {
use std::sync::Arc;

use walletkit::authenticator::artifacts::embedded::EmbeddedZkArtifacts;
use walletkit::requests::ProofRequest;
use walletkit::storage::CredentialStore;
use walletkit::{Authenticator, Environment};

async fn prove(
    seed: Vec<u8>,
    store: Arc<CredentialStore>,
    request_json: &str,
    now: u64,
) -> Result<String, Box<dyn std::error::Error>> {
    let authenticator = Authenticator::init_with_defaults(
        seed,
        None, // rpc_url: use the default.
        &Environment::Staging,
        None, // region: use the default.
        Arc::new(EmbeddedZkArtifacts::new()),
        store,
    )
    .await?;
    authenticator.init_storage(now)?;

    let request = ProofRequest::from_json(request_json)?;
    let response = authenticator.generate_proof(&request, Some(now)).await?;
    Ok(response.to_json()?)
}
}

In this function, now is the current time in Unix seconds. Send the JSON that it returns back to the relying party.

On iOS and Android, use CachingZkArtifacts instead of EmbeddedZkArtifacts when the keys are compressed, so that WalletKit decompresses them only once.

Proof of Embedding Similarity requests

generate_proof doesn’t answer a Proof of Embedding Similarity request (WIP-202): it returns an InvalidInput error for proof_type. Check proof_type() before you call it. For an EmbeddingSimilarity request, embedding_similarity() returns the RP’s challenge_hash and whether it requires an Authenticator Assertion Token. The RP signs only the hash, so call matches_challenge on the challenge image it sends before you use the image. The browser package doesn’t expose these methods yet.

Issuer ownership proofs (iOS and Android)

With the issuers feature, call issuers::fetch_ownership_proof_challenge with an Environment, an explicit challenge type string (such as "enrollment" or "teedi_migration"), a RequestIntegrityProvider, and a UserAgentBuilder. The mobile app supplies the challenge type. WalletKit does not validate the input or returned challenge type value.

The host configures the provider for the challenge service’s audience and obtains the attestation-gateway token. Each prepared RequestIntegritySession pairs that token with its matching hardware signer. WalletKit constructs and signs the HTTP request; private keys stay with the host. The callbacks live in request_integrity and are also available through flamingo.

The result preserves the service’s fields: challenge_id, hex nonce, challenge_type, and RFC 3339 expires_at. Parse the nonce with FieldElement::try_from_hex_string before passing it to Authenticator::prove_credential_sub, using the context specified for the issuer operation. Retain challenge_id for proof submission.

Fetching makes one attempt without redirects, with a 10-second HTTP timeout. Signing uses the shared integrity deadline. Failures return WalletKitError.

Legacy World ID 3.0 proofs

The v3 feature adds the World ID 3.0 API in the v3 module. The Swift and Kotlin packages include it; the browser package doesn’t. docs.rs builds the crate without v3, so read its documentation in the v3 module source or with cargo doc --features v3.