Proposal: a neutral pre-payment recipient hook in the x402 action provider (inspect payTo before paying)
- Dominant language
- TypeScript
- Stars
- 1.3k
- Forks
- 815
- Avg merge
- 13h 31m
- Merged PRs (30d)
- 2
Description
The x402 action provider gates payments on two axes today — **host** (`isUrlAllowed`) and **amount** (`validatePaymentLimit`) — but nothing lets an operator inspect the **payment recipient wallet** (`payTo`) before `wrapFetchWithPayment` signs in `retryWithX402`.
**The gap.** "Is the address my agent is about to send USDC to sanctioned / a known drainer / phishing?" is a distinct axis from host-allowlist and amount-cap, and arguably the one an autonomous payer most wants closed before signing. The selected requirements already carry `payTo` (it is on `PaymentRequirements`), so the data is in hand — there is just no decision point exposed to config.
**Precedent.** The official `@x402` core client already exposes `onBeforePaymentCreation(context)` returning `{ abort, reason }`, with `context.selectedRequirements.payTo` available. AgentKit wraps `@x402/fetch` but does not surface an equivalent pre-pay decision point to `x402ActionProvider` config.
**Proposal.** A neutral, optional config hook — e.g.:
```ts
beforePayment?: (req: { payTo: string; network: string; scheme: string; amountUsdc: number; url: string })
=> { allow: boolean; reason?: string } | Promise<{ allow: boolean; reason?: string }>;
```
evaluated in `retryWithX402` **right after `validatePaymentLimit` and before `wrapFetchWithPayment`** — same shape as the existing `isUrlAllowed` / `validatePaymentLimit` gates. It just hands the operator the selected requirements and lets them allow/deny. No vendor coupling — the hook is provider-agnostic.
**Use case / one implementation.** Recipient sanctions + address-reputation screening before an autonomous send. `anchor-x402-safe-pay` (npm/PyPI) is one drop-in that returns an allow/review/block verdict for a `payTo`, but the hook itself is generic.
Happy to send the PR (config field + hook eval in `retryWithX402` + a test, mirroring `validatePaymentLimit`) if you are open to the addition — proposing first since it is a new public config surface.
Contributor guide
Assessment
This issue has not been assessed yet.