- Made the
axumextractor use route-aware expected-request verification by default. High-levelMppChargeextraction now forwards the route amount into verification so built-in Tempo and Stripe challengers compare incoming credentials against the route's expected charge request instead of trusting the echoed request alone. (by @BrendanRyan, #213)
- Added
ChargeMethod::with_fee_payer_policy_override()for per-server tuning of the fee-sponsor policy (max_gas,max_fee_per_gas,max_priority_fee_per_gas,max_total_fee,max_validity_window_seconds), with per-chain defaults matching mppx#342. (by @stevencartavia, #211)
- Fixed
credential.sourceDID mismatch between $0 proofs and paid charges in Keychain signing mode. The proof path now uses the wallet address (matching mppx and the paid charge path). Server-sideverify_prooffalls back to an on-chain keychain lookup when the recovered signer differs from the source address. (by @BrendanRyan, #209)
- Cache chain ID in
ChargeMethodto avoid a redundanteth_getChainIdRPC call (~270ms) on everyverify()invocation. The chain ID is fetched once on the first call and reused for all subsequent verifications. (by @BrendanRyan, #198) - Use
eth_sendRawTransactionSync(EIP-7966) instead ofeth_sendRawTransaction+ polling for receipt. The Tempo node returns the full receipt in a single blocking call, eliminating the client-side polling loop and reducing broadcast latency from 0.5–7.5s to ~500ms. (by @BrendanRyan, #198)
- Enforced fail-closed behavior for the
expiresfield inverify_hmac_and_expiry. Credentials missing theexpiresfield are now rejected with aCredentialMismatcherror instead of being silently accepted. Session challenges now include a default expiry. (by @EvanChipman, #194) - Fixed busy loop in
serve()caused by defaultwait_for_update()returning immediately instead of pending. (by @EvanChipman, #194) - Fixed
split_payment_challengesto handle leading whitespace in header values. Added tests for merged comma-separated challenges and quoted"Payment"boundaries. (by @stevencartavia, #170)
- Added zero-amount proof credential support for identity flows. Introduced a new
PayloadType::Proofvariant with EIP-712 signing via a newproofmodule, enabling clients to authenticate without sending a blockchain transaction. UpdatedTempoCharge,TempoProvider, and server-side verification to handle zero-amount challenges with signed proofs. (by @BrendanRyan, #182)
- Bind payee and currency validation to all session actions (open, voucher, close, topUp). (by @horsefacts, #188)
- Client now matches challenges by
provider.supports(method, intent)instead of assuming a single challenge, mirroring the mppx TypeScript SDK. BothPaymentExt(fetch) andPaymentMiddlewareparse all challenges and select the first one the provider supports. (by @grandizzy, #185) - Added
HttpError::NoSupportedChallengevariant for when a 402 response contains no challenge matching the provider's supported methods. (by @grandizzy, #185)
- Added split payments support to Tempo charge verification and transaction building. Extended
TempoChargeandTempoChargeExtto parse and propagate split recipients frommethodDetails, and refactored transfer call construction and verification to handle multiple transfers using order-insensitive matching. (by @BrendanRyan, #187)
- Fixed a timing side-channel in HMAC challenge ID verification by replacing non-constant-time string comparison with
constant_time_eq. Added anast-greplint rule to prevent future regressions. (by @BrendanRyan, #175)
- Fixed a race condition in
ChannelStoreAdapterwhere concurrentupdate_channelcalls for the same channel could overwrite each other. Added per-channel async mutex locking to serialize read-modify-write operations within a single process, along with tests reproducing the original race. (by @BrendanRyan, #177)
- Added a Stripe Shared Payment Token (SPT) example demonstrating the full 402 → challenge → credential → retry flow using Stripe's payment method. Includes a server with SPT proxy endpoint and a headless client using a test card. (by @BrendanRyan, #172)
- Added
fee_payer()andchain_id()getters toMpp. (by @BrendanRyan, #172) - Added Stripe payment method support (
method="stripe",intent="charge") with client-sideStripeProviderfor SPT creation, server-sideChargeMethodfor PaymentIntent verification, andMpp::create_stripe()builder integration. Addedstripeandintegration-stripefeature flags backed byreqwest. (by @BrendanRyan, #172)
- Fixed multiple payment bypass and griefing vulnerabilities (GHSA-fxc9-7j2w-vx54). (by @BrendanRyan, #172)
- Bumped
alloydependency from 1.7 to 1.8 andtempo-alloy/tempo-primitivesfrom 1 to 1.5 across the main crate and all examples. (by @BrendanRyan, #172) - Disabled tempo lint PR comments while keeping the lint CI check enforced. (by @BrendanRyan, #172)
- Fixed
base64url_decodeto accept standard base64 (+,/,=padding) in addition to URL-safe base64, following Postel's law and aligning with the mppx TypeScript SDK behavior. Added tests covering standard base64 with padding, URL-safe without padding, and standard alphabet without padding in bothtypes.rsandheaders.rs. (by @BrendanRyan, #172)
- Refactored Tempo client to use
tempo_alloytypes instead of local duplicates. Removed the localabi.rsmodule and replaced local ABI definitions (ITIP20,IStablecoinDEX,IAccountKeychain) with imports fromtempo_alloy::contracts::precompiles. Simplified gas estimation to use the provider'sestimate_gasmethod viaTempoTransactionRequestinstead of manual JSON-RPC construction. (by @BrendanRyan, #143)
- Migrated tempo dependencies (
tempo-alloy,tempo-primitives) from git dependencies to crates.io versioned dependencies, and addedcargo publishto the release workflow with registry token support. (by @BrendanRyan, #142)
- Fixed core problem type base URI to use the canonical
https://paymentauth.org/problemsdomain instead of the temporary GitHub Pages URL. (by @BrendanRyan, #142)
- Added fee payer support to the Tempo payment provider. The client now builds 0x76 transactions with expiring nonces and a placeholder fee payer signature, and the server co-signs them by recovering the sender, setting the fee token, and re-encoding as a standard 0x76 transaction with both signatures. (by @BrendanRyan, #89)
- Added comprehensive integration and unit test coverage across client fetch, client middleware, MCP payment roundtrip, server middleware, server HMAC challenge verification, and SSE metered streaming flows. Also added a
feature-matrixCI job to validate all feature flag combinations, and introducedMpp::new_with_configtest helper and madedetect_realmpub(crate). (by @BrendanRyan, #89) - Added network-specific default currencies for Tempo, defaulting to USDC (USDC.e) on mainnet and pathUSD on testnet. Deprecated the
DEFAULT_CURRENCYconstant in favor ofDEFAULT_CURRENCY_MAINNETandDEFAULT_CURRENCY_TESTNET. (by @BrendanRyan, #89) - Added
TempoChargebuilder API (from_challenge() → sign() → into_credential()), gas resolution (resolve_gas()andresolve_gas_with_stuck_detection()for mempool stuck-tx replacement),SignOptionsfor overriding nonce/gas/signing parameters, andTempoClientErrorwithclassify_rpc_error()for structured error classification. Movedabi.rsfromprotocol::methods::tempotoclient::tempoand consolidated theITIP20sol! definition. (by @BrendanRyan, #89) - Added end-to-end support for the
0x78fee payer envelope format, enabling clients to request gas sponsorship by sending a0x78 || RLP(...)encoded transaction that servers co-sign and broadcast as a standard0x76Tempo transaction. Extended server-side verification to accept both0x76and0x78transaction types, addedsign_and_encode_fee_payer_envelopesigning helpers, and added integration tests asserting on-chain fee payer and sender addresses. (by @BrendanRyan, #89) - Added integration tests for the MPP charge flow against a live Tempo blockchain. Introduced an
integrationfeature flag, updated dev dependencies (axum,reqwest,hex, tokionetfeature), added atest-integrationMakefile target, and addedtests/integration_charge.rswith E2E tests covering health checks, 402 challenge flow, full charge round-trips, and auth scheme validation. (by @BrendanRyan, #89)
- Added comprehensive test coverage for session provider, channel store, and session verification logic. Tests cover voucher sending edge cases, channel state management, HMAC validation, and
SessionVerifyResultdebug formatting. (by @BrendanRyan, #89) - Auto-detect
realmfrom environment variables inMpp::create(). ChecksMPP_REALM,FLY_APP_NAME,HEROKU_APP_NAME,HOST,HOSTNAME,RAILWAY_PUBLIC_DOMAIN,RENDER_EXTERNAL_HOSTNAME,VERCEL_URL,WEBSITE_HOSTNAMEin order, falling back to"MPP Payment". (by @BrendanRyan, #89) - Updated URLs from
machinepayments.devtompp.devin README and removed "web3" keyword from Cargo.toml metadata. (by @BrendanRyan, #89) - Added auto-detection of
realmfrom environment variables inMpp::create(). ChecksMPP_REALM,FLY_APP_NAME,HEROKU_APP_NAME,HOST,HOSTNAME,RAILWAY_PUBLIC_DOMAIN,RENDER_EXTERNAL_HOSTNAME,VERCEL_URL, andWEBSITE_HOSTNAMEin order, falling back to"MPP Payment". (by @BrendanRyan, #89) - Introduced
TempoClientErrorenum scoped underclient::tempofor typed Tempo-specific client errors (AccessKeyNotProvisioned, SpendingLimitExceeded, InsufficientBalance, TransactionReverted). AddedMppError::Tempovariant gated onclient + tempofeatures withclassify_rpc_errorto parse RPC error messages into typed variants, replacing brittle string matching in downstream consumers. (by @BrendanRyan, #89) - Added
TempoSigningModeenum (Direct/Keychain) and centralized transaction helpers for client-side Tempo payments. Newclient::signingmodule providessign_and_encode/sign_and_encode_asyncwith keychain envelope support. Newclient::tx_buildermodule providesTempoTxOptions,build_tempo_tx,estimate_gas,build_estimate_gas_request, andbuild_charge_credential. UpdatedTempoProvider,TempoSessionProvider, andcreate_open_payloadto use the new signing mode abstraction, eliminating duplicated transaction construction logic across consumers. Fixed potentialu64overflow inparse_gas_estimateby usingchecked_add. Added 46 new unit tests (432 → 478) covering signature variant correctness, encoding boundary conditions, escrow resolution priority, deposit edge cases, re-export verification, and gas estimate overflow protection. (by @BrendanRyan, #89) - Added client and protocol helpers upstreamed from presto:
PaymentChallenge::is_expired()andexpires_at()for RFC 3339 challenge expiry checksTempoNetworkenum withfrom_chain_id(),default_rpc_url(), anddefault_currency()lookupsclient::tempo::keychainmodule withquery_key_spending_limit()andlocal_key_spending_limit()for Tempo access key spending limit queries- ABI encoding helpers (
encode_transfer,encode_approve,encode_swap_exact_amount_out,DEX_ADDRESS) inprotocol::methods::tempo::abi PaymentChallenge::validate_for_charge()andvalidate_for_session()for common challenge validationnetwork()convenience methods onTempoChargeExtandTempoSessionExtparse_memo_bytes()utility for hex memo string to 32-byte array conversionextract_tx_hash()utility for extracting transaction hashes from base64url receipts (by @BrendanRyan, #89)
- Added Axum middleware support with extractors and response types, updated library description to "402 Protocol", and made SSE stream pluggable by returning a
Streaminstead ofReceiver. (by @BrendanRyan, #59)
- Fixed parameter parsing to reject duplicate parameters, empty challenge IDs, and non-ISO8601 timestamp formats in conformance with protocol strictness requirements. (by @BrendanRyan, #59)
- Simplified server API with dollar amounts and smart defaults. Added
Mpp::create()andmpp.charge("1")for one-line payment setup. - Added default 5-minute expiration for challenges and
prepare_requesthook for request customization. - Aligned Rust SDK with mppx TypeScript SDK for cross-language consistency.
- Removed failed receipt state — server now returns 402 for payment failures per IETF spec.
- Fixed tempo payment method to match TypeScript SDK behavior. Fixed 402 responses for failed receipts per spec.
- Updated
randdependency from 0.8 to 0.9. (by @BrendanRyan, #56)
- Mandated JCS (RFC 8785) for canonical JSON serialization of request parameters by replacing
serde_json::to_stringwithserde_json_canonicalizer::to_stringthroughout the protocol layer. (by @BrendanRyan, #56) - Updated currency address from AlphaUSD to PathUSD across all examples, documentation, and tests. (by @BrendanRyan, #56)
- Normalized error codes to kebab-case format per IETF spec update (§8.2). (by @BrendanRyan, #56)
- Updated documentation URL and optimized CI workflows. Added GitHub Pages documentation deployment, switched to cargo-hack for feature testing, and pinned release workflow to commit SHA. (by @BrendanRyan, #56)