X402.Paywall.Default (X402 v0.6.0)

Copy Markdown View Source

Self-contained HTML paywall page for browser-facing 402 responses.

Renders a single lean page — inline CSS, no external requests, no build step — from a v2 PaymentRequired payload:

  • the resource description plus amount, asset, network, and recipient for every advertised payment option
  • the exact Base64 PAYMENT-REQUIRED header value for tooling, with manual retry instructions
  • a minimal EIP-1193 (window.ethereum) payment flow for "exact" EVM options using the default eip3009 asset transfer method: connect a wallet, sign the TransferWithAuthorization typed data via eth_signTypedData_v4, assemble the v2 PaymentPayload, and retry the request with a PAYMENT-SIGNATURE header

Without a browser wallet — or when no advertised option is wallet-payable — the page degrades to the requirement details and the manual header instructions. All interpolated values are HTML-escaped and the embedded configuration JSON is encoded script-safe, so route descriptions and service names cannot inject markup.

Configure it through X402.Plug.PaymentGate:

plug X402.Plug.PaymentGate,
  paywall: X402.Paywall.Default,
  routes: [...]

Summary

Functions

Returns a human-readable display name for a CAIP-2 network identifier.

Renders the default HTML paywall page.

Functions

network_display_name(network)

(since 0.6.0)
@spec network_display_name(String.t()) :: String.t()

Returns a human-readable display name for a CAIP-2 network identifier.

Examples

iex> X402.Paywall.Default.network_display_name("eip155:8453")
"Base"

iex> X402.Paywall.Default.network_display_name("eip155:999999")
"EVM chain 999999"

iex> X402.Paywall.Default.network_display_name("otherchain:mainnet")
"otherchain:mainnet"

render(payment_required, conn_info)

(since 0.6.0)
@spec render(map(), X402.Paywall.conn_info()) :: {:ok, iodata()} | {:error, term()}

Renders the default HTML paywall page.

Returns {:error, reason} when the payload cannot be encoded as a PAYMENT-REQUIRED header value (see X402.PaymentRequired.encode/1).

Examples

iex> payment_required = %{
...>   "x402Version" => 2,
...>   "error" => "PAYMENT-SIGNATURE header is required",
...>   "resource" => %{
...>     "url" => "https://example.com/premium",
...>     "description" => "Premium report",
...>     "mimeType" => "application/json"
...>   },
...>   "accepts" => [
...>     %{
...>       "scheme" => "exact",
...>       "network" => "eip155:84532",
...>       "amount" => "10000",
...>       "asset" => "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
...>       "payTo" => "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
...>       "maxTimeoutSeconds" => 60,
...>       "extra" => %{"name" => "USDC", "version" => "2"}
...>     }
...>   ],
...>   "extensions" => %{}
...> }
iex> conn_info = %{method: "GET", request_path: "/premium", status: 402}
iex> {:ok, html} = X402.Paywall.Default.render(payment_required, conn_info)
iex> html =~ "Premium report" and html =~ "Base Sepolia"
true