Packages
Autonomous payment capabilities for Raxol agents. Xochi cross-chain intent settlement, x402/MPP auto-pay, wallet management, and spending controls.
Current section
Files
Jump to
Current section
Files
lib/raxol/payments/protocol.ex
defmodule Raxol.Payments.Protocol do
@moduledoc """
Behaviour for payment protocol implementations.
Each protocol handles a specific 402 payment flow. The auto-pay plugin
tries each configured protocol's `detect?/2` to find one that matches
the server's 402 response, then delegates signing to that protocol.
## Implementations
- `Raxol.Payments.Protocols.X402` -- Coinbase x402 (ERC-3009)
- `Raxol.Payments.Protocols.MPP` -- Stripe/Tempo Machine Payments Protocol
- `Raxol.Payments.Protocols.Riddler` -- cross-chain intents (deprecated, delegates to Xochi)
- `Raxol.Payments.Protocols.Xochi` -- cross-chain private payments (agent-facing)
"""
@type headers :: [{String.t(), String.t()}]
@type challenge :: map()
@type receipt :: map()
@doc """
Check if this protocol can handle the given 402 response.
Inspects the response status and headers to determine if this
protocol's payment flow applies.
"""
@callback detect?(status :: integer(), headers :: headers()) :: boolean()
@doc """
Parse the 402 response headers into a challenge map.
Extracts payment requirements (price, currency, recipient, network)
from the protocol-specific headers.
"""
@callback parse_challenge(headers :: headers()) ::
{:ok, challenge()} | {:error, term()}
@doc """
Build authorization headers for the payment.
Signs the challenge using the provided wallet module and returns
headers to attach to the retry request.
"""
@callback build_payment(challenge :: challenge(), wallet :: module()) ::
{:ok, headers()} | {:error, term()}
@doc """
Parse the payment receipt from a successful response.
Extracts confirmation details (tx hash, amount settled, etc.)
from the response headers after a successful paid request.
"""
@callback parse_receipt(headers :: headers()) ::
{:ok, receipt()} | {:error, term()}
@doc """
Extract the payment amount from a parsed challenge.
Used by the spending policy to check budget before signing.
"""
@callback amount(challenge :: challenge()) :: Decimal.t()
@doc "Human-readable protocol name."
@callback name() :: String.t()
@doc """
Resolve a protocol atom to its implementation module.
"""
@spec resolve(atom()) :: module()
def resolve(:x402), do: Raxol.Payments.Protocols.X402
def resolve(:mpp), do: Raxol.Payments.Protocols.MPP
def resolve(:riddler), do: Raxol.Payments.Protocols.Riddler
def resolve(:xochi), do: Raxol.Payments.Protocols.Xochi
def resolve(module) when is_atom(module) do
if Code.ensure_loaded?(module) and function_exported?(module, :detect?, 2) do
module
else
raise ArgumentError, "unknown payment protocol: #{inspect(module)}"
end
end
end