@leash/seller-kit mounts the real @x402/hono middleware on a list of METHOD /path routes and resolves payTo to the seller agent’s Asset Signer PDA so funds land directly in the agent’s treasury.
import { Hono } from 'hono';
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
import { mplCore } from '@metaplex-foundation/mpl-core';
import { createSeller } from '@leash/seller-kit';

const umi = createUmi('https://api.devnet.solana.com').use(mplCore());
const app = new Hono();

createSeller(app, {
  umi,
  sellerAgent: { asset: '<your Core asset mint>' },
  routes: {
    // Primary settlement currency + optional extra stables in x402 `accepts[]`.
    // Buyers can pay in any listed mint (same atomic amount per option).
    'POST /tag': {
      price: '$0.001',
      description: 'Tag a payload',
      currency: 'USDC',
      acceptsCurrencies: ['USDG'], // also accept USDG on the same route
    },
  },
  onReceipt: async (r) => {
    await fetch(`http://localhost:8787/a/${r.agent}/receipts`, {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify(r),
    });
  },
});

app.post('/tag', (c) => c.json({ tagged: true }));

What createSeller actually does

  1. Resolves the seller agent’s Asset Signer PDA via mpl-core and derives the on-chain destination for SPL transfers (payTo). All x402 settlements credit this PDA, so the agent’s treasury balance grows automatically as buyers pay.
  2. Builds a createSvmResourceServer (from @leash/seller-kit/x402) bound to devnet-facilitator.leash.market on solana-devnet (or the network you configure) by default. Other facilitators are fully supported — see Configuring the facilitator. The facilitator pays the network fee on payTo so neither the seller nor the buyer needs SOL on the receiving side.
  3. Registers paymentMiddlewareFromHTTPServer from @x402/hono for each route. Unauthenticated requests get 402 Payment Required with a base64-encoded PAYMENT-REQUIRED header that lists the accepts[] (one entry per accepted stablecoin: asset mint, atomic amount, payTo, fee payer, scheme). When you set currency plus acceptsCurrencies, the seller advertises multiple mints at the same price so buyers can pick e.g. USDG while the link is priced in USDC.
  4. After settlement, the onAfterSettle hook produces an earn ReceiptV1 with the real tx_sig + payment_requirements_hash and ships it through the resolved receipt sink (see below).

Receipts by default

onReceipt is now optional. When LEASH_API_URL + LEASH_API_KEY (or LEASH_RUNNER_URL) are set in the environment, every earn receipt is forwarded automatically to those destinations. Pass onReceipt: false to opt out, or set receipts: { runnerUrl, apiUrl, apiKey } to override. The full defaulting logic is shared with the buyer kit and documented in Receipts by default.

Probing without paying

curl -i -X POST http://localhost:3001/tag -d '{"hello":"leash"}'
# HTTP/1.1 402 Payment Required
# PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6Mi…
Decode PAYMENT-REQUIRED (base64 → JSON) to see the offer. The web playground at /seller does this for you.

Configuring the facilitator

The default is https://devnet-facilitator.leash.market (devnet) / https://facilitator.leash.market (mainnet). To use a different HTTPS-compatible facilitator:
import { createSvmResourceServer } from '@leash/seller-kit/x402';

const server = createSvmResourceServer({
  network: 'solana-devnet',
  payTo,
  asset: '<USDC mint>',
  facilitatorUrl: 'https://your-facilitator.example.com',
});
See Real x402 on Solana for the protocol-level walkthrough.

HTTP equivalent (polyglot SDKs)

If you’re not on TypeScript, the same primitives are exposed as REST under /v1/seller/* and /v1/payment-links. The Seller utilities page covers parse-price, facilitator, networks, and pay-to. The Payment links page covers the hosted-paywall shape — declare a price + a response template, get a sharable URL. Both surfaces produce the same on-chain result and the same explorer entries as createSeller does in-process.