This document tracks compliance against the x402-foundation/x402 scheme_exact_cardano.md spec, by section.
cardano402 implements the default (address-to-address) asset transfer method end-to-end with all six spec-mandated facilitator verification rules, plus four additional defensive checks (CBOR validity, witness presence, fee bounds, min UTXO).
The script asset transfer method is recognised at the schema level
but the runtime verifier returns a structured method_not_implemented
reason. Any other non-default method literal is rejected with
method_not_supported. The schemas in src/sdk/methods.ts give a
clear contract for future implementers of script.
| Field | Status |
|---|---|
x402Version |
Strict literal 2 (rejects 1). |
error |
Optional, supported. |
resource.{url,description,mimeType} |
Supported. |
accepts[].scheme: "exact" |
Strict literal. |
accepts[].network |
Validated via CAIP-2 regex. |
accepts[].amount |
String, BigInt-safe. |
accepts[].asset |
lovelace or policyId.assetNameHex. |
accepts[].payTo |
Bech32 string. |
accepts[].maxTimeoutSeconds |
Defaults 300; spec recommends 600. |
accepts[].extra |
Open record; runtime branch on assetTransferMethod. |
Both header names accepted on the wire: Payment-Signature and
PAYMENT-SIGNATURE. Payload schema PaymentSignaturePayloadSchema now
enforces:
x402Version: 2strictaccepted: <PaymentAccept>payload.transaction: <base64 string>payload.nonce: <txHash>#<index>— required whenchain.verification.requireNonce = true(default)
| # | Rule | cardano402 check | Status |
|---|---|---|---|
| 1 | Network validation | checkNetwork |
Implemented |
| 2 | Recipient verification | checkRecipient |
Implemented |
| 3 | Amount verification | checkAmount |
Implemented |
| 4 | Asset verification | checkAmount + checkTokenSupported |
Implemented (plus token registry) |
| 5 | Nonce / replay prevention | checkNonce |
Implemented (Track A1) |
| 6 | TTL / expiry | checkTtl |
Implemented |
Plus cardano402 extras (defensive, not required by spec): checkCborValid,
checkWitness, checkMinUtxo, checkFee.
Both header names emitted on response: X-Payment-Response (canonical)
and PAYMENT-RESPONSE (compat). Payload schema includes
extensions.status with confirmed | mempool per spec. cardano402
defaults to confirmed_only mode; emit-on-mempool requires explicit
operator opt-in (chain.verification.confirmationMode = "allow_mempool").
| Method | Schema | Verifier | Settlement |
|---|---|---|---|
default |
Yes | Full 11-check pipe | Full |
script |
Yes | Returns method_not_implemented |
Refuses to settle |
| any other | n/a | Returns method_not_supported |
Refuses to settle |
POST /verify and POST /settle accept either:
{x402Version, paymentPayload: <object>, paymentRequirements}(cardano402 native){x402Version, paymentHeader: <base64-string>, paymentRequirements}(base x402)
The internal verifier always sees the parsed object form. See
src/verify/request-shape.ts.
- Script method verifier. Requires a Plutus parameter applier
compatible with
@lucid-evolution/lucidand a datum decoder. - Strict spec-conformance test fixtures. When upstream
x402-foundation/x402ships test fixtures for the Cardano scheme, wire them intotests/integration/to lock in alignment. Until then we self-test against the Zod schemas plus hand-built tx fixtures.
The base x402 spec and the Cardano spec disagree on a few details (documented in upstream issues). cardano402's posture:
- Request header: accept both
PAYMENT-SIGNATUREandX-PAYMENT. DocumentPayment-Signature(cardano402 client default). - Response header: emit both
X-Payment-Response(canonical, matches base x402) andPAYMENT-RESPONSE(matches Cardano spec literal). - Verify body: accept both
paymentPayload(object) andpaymentHeader(base64 string).
We will remove deprecated forms one major version after upstream reconciles, with at least one release of overlap.