Built-in X402.Scheme for upto payments on EVM (eip155:*) networks.
Implements both roles:
- Client — signs a Permit2
PermitWitnessTransferFromthroughX402.Permit2, producing the%{"signature" => ..., "permit2Authorization" => ...}scheme payload. The signedpermitted.amountis the advertised maximum; the server settles for the actual usage, up to that ceiling. An entry is signable when its network is EVM (eip155:*) and itsextracarries thefacilitatorAddressthe witness must bind (facilitators announce it viaGET /supported—X402.Facilitator.supported/1); signing without it fails with{:error, {:missing_extra, "facilitatorAddress"}}. - Server —
X402.Scheme.validate_payload/3validates that the payment value the client signed does not exceed the advertised maximum (the requirements'amount, withmaxPriceandmaxAmountRequiredfallbacks), recognizing the Permit2 (permit2Authorization.permitted.amount),maxAmount,value, and EIP-3009authorization.valuepayload shapes. Failures are{:error, {:invalid_upto_payment, reason}}— seevalidation_error/0.
Pre-checks reuse the shared EIP-3009 authorization checks
(X402.Scheme.EVM.authorization_precheck/3 — payTo binding and validity
window) without the exact-amount equality: for upto, the signed value
is a ceiling, not the settled amount. Permit2 payloads carry no
payload.authorization map and pass through to the facilitator.
Summary
Types
Reasons an upto payment fails ceiling validation.
Functions
Returns ["eip155:*"] — every EVM network.
Runs X402.Scheme.EVM.authorization_precheck/3 without exact-amount
equality — for upto, the signed value is a ceiling.
Returns "upto".
Signs the Permit2 upto scheme payload via X402.Permit2.sign_upto/2.
Whether the client can sign this requirements entry.
Validates that the signed payment value stays within the ceiling.
Types
Functions
@spec networks() :: [String.t()]
Returns ["eip155:*"] — every EVM network.
Examples
iex> X402.Scheme.UptoEVM.networks()
["eip155:*"]
@spec precheck(map(), map(), keyword()) :: :ok | {:error, {:precheck_failed, X402.Scheme.EVM.precheck_failure()}}
Runs X402.Scheme.EVM.authorization_precheck/3 without exact-amount
equality — for upto, the signed value is a ceiling.
@spec scheme() :: String.t()
Returns "upto".
Examples
iex> X402.Scheme.UptoEVM.scheme()
"upto"
@spec sign(map(), X402.Signer.t(), keyword()) :: {:ok, map()} | {:error, term()}
Signs the Permit2 upto scheme payload via X402.Permit2.sign_upto/2.
The client's build options are ignored — the authorization is valid
immediately (witness.validAfter "0") and expires after the
requirements' maxTimeoutSeconds, mirroring the reference SDKs.
Whether the client can sign this requirements entry.
Requires an EVM (eip155:*) network the Permit2 domain can be derived
from and a facilitatorAddress in extra for the witness binding.
Examples
iex> X402.Scheme.UptoEVM.signable?(%{
...> "network" => "eip155:84532",
...> "extra" => %{"facilitatorAddress" => "0x2222222222222222222222222222222222222222"}
...> })
true
iex> X402.Scheme.UptoEVM.signable?(%{"network" => "eip155:84532", "extra" => %{}})
false
@spec validate_payload(map(), map(), keyword()) :: :ok | {:error, {:invalid_upto_payment, validation_error()}}
Validates that the signed payment value stays within the ceiling.
Examples
iex> X402.Scheme.UptoEVM.validate_payload(
...> %{"payload" => %{"value" => "9000"}},
...> %{"amount" => "10000"},
...> []
...> )
:ok
iex> X402.Scheme.UptoEVM.validate_payload(
...> %{"payload" => %{"value" => "10001"}},
...> %{"amount" => "10000"},
...> []
...> )
{:error, {:invalid_upto_payment, :payment_value_exceeds_max_price}}