Executors handle the protocol-specific details of moving money. The decision
engine knows nothing about protocols — it produces an ALLOW / BLOCK / ESCALATE
decision. If ALLOW, the Wallet dispatches to the correct executor.
- Create
ledge/execution/your_protocol.py - Subclass
PaymentExecutor - Implement
async execute(tx, signer) -> ExecutionResult - Register it in
Wallet(executors={"your_protocol": YourExecutor()})
Nothing else changes — the decision engine, models, and audit layer are completely unaware of your protocol.
Pays for HTTP resources using the x402 protocol.
- Signs an EIP-712 payload via the
SigningProvider - Sends the signed payment header with the HTTP request
- Returns the HTTP response body on success
Direct on-chain USDC ERC-20 transfer. Not yet implemented.
Every executor returns an ExecutionResult:
| Field | Type | Description |
|---|---|---|
tx_hash |
str |
On-chain transaction hash |
success |
bool |
Whether the execution succeeded |
protocol |
Protocol |
"x402" or "transfer" |
amount_usd |
float |
Amount that was transferred |
network |
str |
Network the tx executed on |
raw_response |
dict or None |
Protocol-specific response payload |