Summary
x402r adds escrow-backed refunds to x402 payments. The Ampersend SDK currently hardcodes scheme: "exact" at every layer — type definitions, adapters, wallets, and the hosted API schema. This makes it impossible for agents to pay for resources protected by alternative x402 schemes like "commerce" (escrow-based payments with refund eligibility).
We'd like to integrate x402r commerce-protected resources with Ampersend agents and are documenting the specific blockers below.
Blockers
1. Scheme dispatch is hardcoded to "exact"
Four places enforce the exact scheme:
| Location |
File |
Issue |
TreasurerSchemeClientV1/V2 |
x402/http/adapter.ts |
readonly scheme = "exact" — x402Client can't find a handler for other schemes |
AccountWallet.createPayment() |
x402/wallets/account/wallet.ts |
Throws WalletError if requirements.scheme !== "exact" |
SmartAccountWallet.createPayment() |
x402/wallets/smart-account/wallet.ts |
Same throw on non-exact |
PaymentRequirements schema |
ampersend/types.ts |
Schema.Literal("exact") with annotation "starting with exact only for MVP" — the hosted treasurer rejects non-exact requirements before they reach the wallet |
Suggested fix: Allow wrapWithAmpersend() to accept a Map<string, SchemeClient> (or similar registry) so callers can register additional scheme handlers. The x402 x402Client already has scheme dispatch built in — the wallet layer just needs to stop short-circuiting it. The API schema would also need to be relaxed for the hosted treasurer.
2. No ReceiveWithAuthorization signing path
The commerce/escrow scheme uses ERC-3009 ReceiveWithAuthorization instead of TransferWithAuthorization. This is required because the escrow contract must be msg.sender when calling receiveWithAuthorization() on the token contract — transferWithAuthorization allows anyone to submit, which breaks the escrow security model.
Currently the SDK only defines TransferWithAuthorization EIP-712 types and signing. There are zero references to ReceiveWithAuthorization in the codebase.
Suggested fix: Add ReceiveWithAuthorization as an alternate EIP-712 signing path, selected by the scheme handler. The struct fields are identical to TransferWithAuthorization — only the primaryType string differs.
3. v2 adapter silently coerces scheme
x402/http/v2-adapter.ts contains:
scheme: v2Req.scheme as "exact",
This casts any scheme value to "exact" at the type level rather than failing or passing it through. A "commerce" requirement would be silently mistyped.
Suggested fix: Remove the cast — pass scheme through as-is and let the scheme dispatch handle validation.
4. Python SDK has the same pattern
The Python SDK (smart_account/exact.py, cosigned.py) has equivalent hardcoding — ValueError on non-exact schemes. Same fixes would apply there.
What integration looks like
With these changes, an Ampersend EOA agent paying for a commerce-protected resource would look like:
import { wrapWithAmpersend } from "@ampersend_ai/ampersend-sdk";
import { commerceSchemeClient } from "@x402r/evm/commerce/client";
const client = wrapWithAmpersend(httpClient, {
wallet: accountWallet,
schemes: new Map([
// exact scheme registered by default
["commerce", commerceSchemeClient],
]),
});
// Agent fetches commerce-protected resource — 402 → escrow payment → response
const response = await client.get("https://api.example.com/protected");
No changes are required on the x402r side. The extra field passthrough has been confirmed working — commerce-specific keys (operatorAddress, escrowAddress, tokenCollector, fee bounds) don't collide with Ampersend's extra usage.
Validated assumptions
- Treasurer interface is scheme-agnostic (approves based on amount, not scheme) — only the API schema blocks non-exact
extra field is preserved throughout the pipeline with no stripping or collisions
- MCP/A2A transports delegate to the wallet layer — no transport changes needed
- x402 v2 protocol is natively supported
Summary
x402r adds escrow-backed refunds to x402 payments. The Ampersend SDK currently hardcodes
scheme: "exact"at every layer — type definitions, adapters, wallets, and the hosted API schema. This makes it impossible for agents to pay for resources protected by alternative x402 schemes like"commerce"(escrow-based payments with refund eligibility).We'd like to integrate x402r commerce-protected resources with Ampersend agents and are documenting the specific blockers below.
Blockers
1. Scheme dispatch is hardcoded to
"exact"Four places enforce the exact scheme:
TreasurerSchemeClientV1/V2x402/http/adapter.tsreadonly scheme = "exact"— x402Client can't find a handler for other schemesAccountWallet.createPayment()x402/wallets/account/wallet.tsWalletErrorifrequirements.scheme !== "exact"SmartAccountWallet.createPayment()x402/wallets/smart-account/wallet.tsPaymentRequirementsschemaampersend/types.tsSchema.Literal("exact")with annotation "starting with exact only for MVP" — the hosted treasurer rejects non-exact requirements before they reach the walletSuggested fix: Allow
wrapWithAmpersend()to accept aMap<string, SchemeClient>(or similar registry) so callers can register additional scheme handlers. The x402x402Clientalready has scheme dispatch built in — the wallet layer just needs to stop short-circuiting it. The API schema would also need to be relaxed for the hosted treasurer.2. No
ReceiveWithAuthorizationsigning pathThe commerce/escrow scheme uses ERC-3009
ReceiveWithAuthorizationinstead ofTransferWithAuthorization. This is required because the escrow contract must bemsg.senderwhen callingreceiveWithAuthorization()on the token contract —transferWithAuthorizationallows anyone to submit, which breaks the escrow security model.Currently the SDK only defines
TransferWithAuthorizationEIP-712 types and signing. There are zero references toReceiveWithAuthorizationin the codebase.Suggested fix: Add
ReceiveWithAuthorizationas an alternate EIP-712 signing path, selected by the scheme handler. The struct fields are identical toTransferWithAuthorization— only theprimaryTypestring differs.3. v2 adapter silently coerces scheme
x402/http/v2-adapter.tscontains:This casts any scheme value to
"exact"at the type level rather than failing or passing it through. A"commerce"requirement would be silently mistyped.Suggested fix: Remove the cast — pass
schemethrough as-is and let the scheme dispatch handle validation.4. Python SDK has the same pattern
The Python SDK (
smart_account/exact.py,cosigned.py) has equivalent hardcoding —ValueErroron non-exact schemes. Same fixes would apply there.What integration looks like
With these changes, an Ampersend EOA agent paying for a commerce-protected resource would look like:
No changes are required on the x402r side. The
extrafield passthrough has been confirmed working — commerce-specific keys (operatorAddress,escrowAddress,tokenCollector, fee bounds) don't collide with Ampersend'sextrausage.Validated assumptions
extrafield is preserved throughout the pipeline with no stripping or collisions