Skip to main content

anchor-x402-safe-pay

Screen a recipient before your agent sends funds. A one-line, wallet-agnostic wrapper that runs an anchor-x402 risk pre-flight (allow / review / block) on the counterparty and only lets the payment through if it's clean.

It wraps the payment your agent already makes — you don't call a new "service", you decorate your send. Works with viem, ethers, x402-fetch, a Solana signer, anything: you pass your own send as a thunk.

Why

Autonomous agents move USDC without a human watching the recipient. safe-pay puts a sanctions + address-reputation check (drainer / phishing / mixer) in the send path, so a payment to a flagged address fails closed instead of draining a wallet.

Install

npm install anchor-x402-safe-pay      # or: pip install anchor-x402-safe-pay

Use — JavaScript / TypeScript

import { guardedSend } from "anchor-x402-safe-pay";

// `paidFetch` is your x402-capable fetch (e.g. from @x402/fetch's
// wrapFetchWithPayment) — it settles the $0.02 screen call for you.
await guardedSend(
  recipient,
  () => wallet.sendUsdc(recipient, amount),   // your real send, runs only if allowed
  { fetchImpl: paidFetch },
);

If the recipient is flagged, guardedSend throws ScreenBlockedError (carrying the full verdict) and your send never runs.

Use — Python

from anchor_safe_pay import guarded_send

# `paid_post(url, json_body) -> dict` is your x402-capable POST (pays the $0.02).
guarded_send(
    recipient,
    lambda: wallet.send_usdc(recipient, amount),   # runs only if allowed
    fetch=paid_post,
)

Register on your client's existing pre-pay hook

Most x402 clients already expose a hook that fires with the recipient (payTo) before signing — you don't need the wrapper, just a decision. screenAllows() is that decision (never throws; folds blockOn/onError so the hook stays a one-liner). Full snippets in examples/:

Official @x402 client (beforePaymentCreation):

x402Client.onBeforePaymentCreation(async (req) => {
  const { ok, verdict } = await screenAllows(req.payTo, { fetchImpl: paidFetch });
  return ok ? undefined : { abort: true, reason: verdict.recommendation };
});

elizaOS plugin-wallet (onBeforePayment → return false to block):

const onBeforePayment = async (req) => (await screenAllows(req.payTo, { fetchImpl: paidFetch })).ok;

faremeter (payerChooser → throw to abort), qntx/r402 (before_payment_creation), and the Python client (on_before_payment_creation) take the same shape — see examples/. Use paidFetch other than the client you're guarding, so screening a payment never recurses.

Verdict → action

/v1/screen returns a recommendation you branch on:

recommendation meaning default
allow clean send runs
review needs a human (elevated risk) held (fail-closed)
block sanctioned / drainer / phishing held

By default blockOn: ["block", "review"] — a review holds. To send on review (e.g. you have your own human-in-the-loop), set blockOn: ["block"] and inspect the thrown verdict:

try {
  await guardedSend(recipient, send, { blockOn: ["block"], fetchImpl: paidFetch });
} catch (e) {
  if (e.verdict.recommendation === "review") await askAHuman(e.verdict);
  else throw e; // hard block
}

Options

  • fetchImpl (JS) / fetch (Py) — required for real use: your x402-capable fetch/POST, so the $0.02 screen call settles. Without it you'll get a 402.
  • blockOn — recommendations that refuse the send. Default ["block", "review"].
  • onError — what to do if the screen call itself fails (network / 402 / anchor down): "block" (default — a safety guard fails safe) or "allow" (anchor downtime never blocks your payments). Choose deliberately.
  • timeoutMs / timeout, endpoint — overridable.

Need the raw verdict without the send? Call screen(address, { fetchImpl }) directly.

Cost

Each guarded send makes one $0.02 USDC /v1/screen call on Base — cheap insurance against a drained payment. The screen degrades to a partial verdict rather than erroring if the reputation layer is briefly unavailable.

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

anchor_x402_safe_pay-0.2.0.tar.gz (9.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

anchor_x402_safe_pay-0.2.0-py3-none-any.whl (5.6 kB view details)

Uploaded Python 3

File details

Details for the file anchor_x402_safe_pay-0.2.0.tar.gz.

File metadata

  • Download URL: anchor_x402_safe_pay-0.2.0.tar.gz
  • Upload date:
  • Size: 9.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for anchor_x402_safe_pay-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5fc365c41d1d1f02a9e1c02d00e76682aacf01ea23d5689667cebeb6b8859c4f
MD5 75e2e4e7666c00aab617a1c02175503b
BLAKE2b-256 d20d7f16e44ade14aca5813b203797d41bc196b6af75408e07486e31c682bc3f

See more details on using hashes here.

Provenance

The following attestation bundles were made for anchor_x402_safe_pay-0.2.0.tar.gz:

Publisher: publish-pypi.yml on hypeprinter007-stack/anchor-x402-safe-pay

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file anchor_x402_safe_pay-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for anchor_x402_safe_pay-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c8293e8511a26c996b51ea1a5fa6830d3aa50b75904cbef46e30da5924e7b989
MD5 acbc6683da9e09c992a6b67342fb5b8a
BLAKE2b-256 b886052aa69c238abde8763815c55aa9b140270e32748201d0d660dd74ae5a3c

See more details on using hashes here.

Provenance

The following attestation bundles were made for anchor_x402_safe_pay-0.2.0-py3-none-any.whl:

Publisher: publish-pypi.yml on hypeprinter007-stack/anchor-x402-safe-pay

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page