Skip to content

feat: multi-protocol support — unified fetcher + omni-challenge (Phase 1)#143

Merged
badjer merged 13 commits intomainfrom
feature/phase1-sdk-client
Mar 31, 2026
Merged

feat: multi-protocol support — unified fetcher + omni-challenge (Phase 1)#143
badjer merged 13 commits intomainfrom
feature/phase1-sdk-client

Conversation

@badjer
Copy link
Copy Markdown
Contributor

@badjer badjer commented Mar 31, 2026

Summary

Phase 1 of multi-protocol integration per MULTI_PROTOCOL_EXECUTION_PLAN.md (Tasks 1.5, 1.6, 1.7).

Client-side (Tasks 1.5 + 1.6):

  • PaymentProtocol type ('atxp' | 'x402' | 'mpp') and ProtocolFlag feature flag function in @atxp/common
  • Strategy pattern in ATXPFetcher: ProtocolHandler interface with X402ProtocolHandler, ATXPProtocolHandler, MPPProtocolHandler
  • protocolFlag(userId, destination) selects handler when multiple match (omni-challenge)
  • Default (no handlers/flag): existing ATXP-MCP flow via checkForATXPResponse() — fully backwards compatible
  • X402 handler calls /authorize/x402 on accounts with connection token auth
  • New @atxp/mpp package for MPP challenge parsing
  • New @atxp/tempo package for Tempo chain + pathUSD support

Server-side (Task 1.7):

  • Omni-challenge builders: buildOmniChallenge(), omniChallengeMcpError(), omniChallengeHttpResponse()
  • detectProtocol() identifies X402 from X-PAYMENT header on retry requests
  • ProtocolSettlement calls auth /verify/{protocol} at request start, /settle/{protocol} at request end
  • Protocol-specific request bodies match auth Zod schemas
  • Settlement only fires on 2xx responses

Related PRs:

  • accounts PR #624 (merged): /authorize/x402 + /authorize/atxp
  • auth PR #228: /verify/{protocol} + /settle/{protocol}

Test plan

  • Unit tests: 34 client + 19 server + 4 express = 57 tests passing
  • Local integration: accounts (8016) + auth (3010) + dev:resource + dev:cli — ATXP flow works end-to-end
  • Verify X402 flow with protocolHandlers + protocolFlag configured

🤖 Generated with Claude Code

badjer and others added 13 commits March 25, 2026 16:08
Task 1.5: Add PaymentProtocol, ProtocolFlag, and ChainFlag types to @atxp/common.
Task 1.6: Refactor ATXPFetcher with strategy pattern for protocol handlers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Task 3.3 — Tempo chain support in SDK:
- Add 'tempo' to Chain/Network types in @atxp/common
- New @atxp/tempo package: TempoAccount, TempoPaymentMaker
- pathUSD token (TIP-20, 6 decimals) with transferWithMemo support
- Chain ID 4217 (mainnet), 42431 (testnet/Moderato)

Task 3.6 — MPP protocol handler:
- New @atxp/mpp package: MPP challenge parsing, MCP error -32042 detection
- MPPProtocolHandler in @atxp/client: detects WWW-Authenticate: Payment
  header and MCP -32042 errors, calls /authorize/mpp, retries with
  Authorization: Payment credential
- protocolFlag='mpp' selects MPP handler from omni-challenge
- Graceful fallback when /authorize/mpp is unavailable

All 228 tests passing across atxp-common, atxp-tempo, atxp-mpp, atxp-client.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Critical:
- Fix native currency to Ether/ETH (matches auth repo)
- Fix response body double-consumption bug in MPPProtocolHandler
- Add TempoModerato to ChainEnum for testnet support

Major:
- Decompose handlePaymentChallenge into extractChallenge,
  buildProspectivePayment, authorizeAndRetry helpers
- Decompose makePayment into checkBalance, classifyError helpers
- Remove dead SSE check in canHandle

Minor:
- Lower JWT log level from info to debug
- Add testnet support to TempoAccount via chainId parameter
- Add vitest.config.ts to atxp-tempo and atxp-mpp packages
- Fix unused variable lint error in tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract makePayment helpers (encodeTransferData, sendAndConfirm) to bring
  method under 50-line limit
- Consolidate duplicated onPaymentFailure patterns into reportFailure helper
  in MPP handler
- Fix reconstructResponse to preserve original response headers and statusText,
  matching X402 handler behavior
- Remove unused @atxp/common and bignumber.js deps from @atxp/mpp package.json
- Add tests for reconstructResponse header preservation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove unused FetchLike import from mppProtocolHandler.ts
- Remove unused ProspectivePayment and PaymentFailureContext imports from protocolHandler.test.ts
- Replace duplicated MCP error detection in canHandle() with hasMPPMCPError()
- Fix unsafe type assertions in classifyError() using instanceof checks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ch block

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…3.3 + 3.6)

feat: Tempo chain support + MPP protocol handler (Tasks 3.3 + 3.6)
Fixes ESLint no-unused-vars error blocking CI on PR #2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AccountIdDestination doesn't carry a connection token, so server
registration was rejected by auth's developerAccountVerifier middleware
(missing X-ATXP-TOKEN). Revert to ATXPAccount which provides the token.
Also point server at localhost:3010 for local testing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix double response body consumption in MPPProtocolHandler by reading
  body once upfront in extractChallenge
- Fix ATXPProtocolHandler to return null instead of throwing, consistent
  with the ProtocolHandler strategy pattern contract
- Add runtime validation for /authorize/x402 and /authorize/mpp responses
  to catch missing paymentHeader/credential fields
- Replace unsafe `as` casts with type guards for account.origin/token
- Add 30s timeout on /authorize/* calls via AbortController
- Add tests for invalid auth responses, malformed headers, and ATXP
  handler strategy pattern compliance

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix /authorize/x402 request body: send selectedPaymentRequirements as
  single object (not the full accepts array) to match accounts Zod schema
- Add auth headers (Basic auth with connection token) to /authorize/x402
  and /authorize/mpp calls so they pass accounts privyAuth middleware
- Don't hardcode 'base' network in selectPaymentRequirements — let x402
  library pick the best match from available options
- Fix MPP extractChallenge() double body consumption: clone response
  before reading so both header and MCP-body paths can read independently
- Update test mock to handle undefined network parameter

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…multi-protocol support

Implements Task 1.7 of the multi-protocol integration plan:
- Server emits omni-challenges containing both ATXP-MCP and X402 payment data
- Credential detection: X-PAYMENT header → X402, ATXP JWT → ATXP-MCP
- ProtocolSettlement routes verify/settle to auth /verify/{protocol} and /settle/{protocol}
- Express middleware: verify at request start, settle at request end
- Omni-challenge formats: HTTP 402 with X402 body + X-ATXP-Payment-Request header (HTTP),
  MCP error -30402 with combined data (MCP SSE)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ProtocolSettlement now builds protocol-specific request bodies:
  X402 sends { payload, paymentRequirements }, ATXP sends
  { sourceAccountId, destinationAccountId, sourceAccountToken, options }
  to match auth service Zod schemas
- detectProtocol no longer misidentifies Bearer JWTs as ATXP payment
  credentials — Bearer tokens in non-MCP requests are OAuth tokens.
  Only X-PAYMENT header is detected (ATXP-MCP flows through MCP path)
- Settlement only fires on successful responses (2xx status codes),
  preventing users from being charged when request handlers error
- Add SettlementContext type for passing protocol-specific data

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@badjer badjer merged commit 37a54ab into main Mar 31, 2026
1 check passed
@badjer badjer deleted the feature/phase1-sdk-client branch March 31, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant