Skip to main content
The ChallengeEngine class orchestrates the full challenge lifecycle: creating challenges, verifying payments, transitioning state, and issuing credentials. It is instantiated internally by createKey0() and shared across all transports (Express, Hono, Fastify, MCP). You rarely construct a ChallengeEngine directly. Use the factory unless you need full control over wiring.

Constructor

Methods

requestAccess

Creates a PENDING challenge for the A2A protocol flow. Idempotent — if a challenge with the same requestId already exists, the existing challenge is returned.
Returns: Promise<X402Challenge> — the challenge object containing challengeId, payment amount, destination wallet, and chainId.

requestHttpAccess

Creates a PENDING challenge for the x402 HTTP flow. Auto-generates a requestId if one is not provided.
Returns: Promise<{ challengeId: string }> — the ID of the created challenge.

submitProof

Verifies a payment on-chain via adapter.verifyProof(), transitions the challenge from PENDING to PAID to DELIVERED, and issues credentials. Used by the A2A protocol flow.
Returns: Promise<AccessGrant> — the grant containing the issued credential (JWT, API key, etc.) from fetchResourceCredentials.
This method performs on-chain verification. It will reject if the transaction does not match the expected amount, destination, or token contract.

processHttpPayment

Handles payment for the x402 HTTP flow. Unlike submitProof, this method skips on-chain verification because the x402 settlement layer has already verified the payment. Creates a challenge if one does not yet exist, then transitions through PAID to DELIVERED.
Returns: Promise<AccessGrant> — the grant containing the issued credential.

preSettlementCheck

Returns a cached AccessGrant if the challenge has already been delivered. Returns null otherwise. Use this to avoid duplicate settlement when a client retries a request that was already fulfilled.
Returns: Promise<AccessGrant | null> — the existing grant, or null if no delivered grant exists.

cancelChallenge

Transitions a challenge from PENDING to CANCELLED. Only pending challenges can be cancelled.
Returns: Promise<void>

State Machine

ChallengeEngine enforces a strict state machine for every challenge. Only valid transitions are permitted; invalid transitions throw a Key0Error.
All transitions are atomic and go through IChallengeStore.transition() to prevent race conditions under concurrent access. For the full state machine specification, see the State Machine page.

Error Handling

All methods throw Key0Error with typed error codes when a failure occurs. Common scenarios include: See the full list of error codes at Error Codes.

Usage Example

In most applications, you interact with ChallengeEngine indirectly through the framework integration. For direct usage: