Skip to main content
A facilitator verifies and settles payments on-chain. By default, faremeter uses the Corbits facilitator (https://facilitator.corbits.dev). If you need to run your own, use @faremeter/facilitator.
pnpm add @faremeter/facilitator hono

When to run your own

  • You need to support custom payment schemes not available on the Corbits facilitator.
  • You want full control over payment verification and settlement.
  • You are running in an environment that cannot reach the Corbits facilitator.
For most development and production use cases, the Corbits facilitator is sufficient.

Basic setup

import { Hono } from "hono"
import { createFacilitatorRoutes } from "@faremeter/facilitator"

const handlers = [
  // Chain-specific handlers
]

const app = new Hono()
app.route("/", createFacilitatorRoutes({ handlers }))

export { app }
createFacilitatorRoutes returns a Hono router with the standard facilitator endpoints: /accepts, /verify, /settle, and /supported.

Creating handlers

Each chain has its own createFacilitatorHandler function that returns a FacilitatorHandler. Install the payment package for the chain you want to support.

Solana handler

pnpm add @faremeter/payment-solana @solana/kit @solana-program/node-helpers
import { createFacilitatorHandler } from "@faremeter/payment-solana/exact"
import { createSolanaRpc } from "@solana/kit"
import { getKeypairFromFile } from "@solana-program/node-helpers"

const rpc = createSolanaRpc(process.env.SOLANA_RPC_URL!)
const feePayerKeypair = await getKeypairFromFile(process.env.SOLANA_PAYER_KEYPAIR!)
const mint = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" // USDC

const solanaHandler = await createFacilitatorHandler(
  "devnet",
  rpc,
  feePayerKeypair,
  mint,
)
Signature: createFacilitatorHandler(network, rpc, feePayerKeypair, mint, config?) The optional config parameter accepts:
OptionTypeDescription
maxRetriesnumberMaximum retries for transaction submission.
retryDelayMsnumberDelay between retries in milliseconds.
maxPriorityFeenumberMaximum priority fee in lamports.
featuresobjectFeature flags (e.g., enableSettlementAccounts).
hooksFacilitatorHooks[]Lifecycle hooks for afterVerify and afterSettle.
const solanaHandler = await createFacilitatorHandler(
  "devnet",
  rpc,
  feePayerKeypair,
  mint,
  {
    maxRetries: 5,
    retryDelayMs: 500,
    hooks: [
      {
        afterSettle: async ({ response, requirements, payment, logger }) => {
          logger.info("Settlement complete", { txHash: response.transaction })
        },
      },
    ],
  },
)

EVM handler

pnpm add @faremeter/payment-evm viem
import { createFacilitatorHandler } from "@faremeter/payment-evm/exact"

const evmHandler = await createFacilitatorHandler(
  { id: 84532, name: "base-sepolia", rpcUrl: process.env.EVM_RPC_URL! },
  process.env.EVM_PRIVATE_KEY!,
  "USDC",
)
Signature: createFacilitatorHandler(chain, privateKey, assetNameOrInfo, opts?)
ParameterTypeDescription
chainChainInfoWithRPCObject with id, name, and rpcUrl.
privateKeystringHex-encoded private key for transaction submission.
assetNameOrInfoAssetNameOrContractInfoAsset name (e.g., "USDC") or contract info object.
optsobjectOptional. network (KnownX402Network) and transport (viem Transport).

Multi-chain configuration

Wire handlers for each chain together and pass them to createFacilitatorRoutes:
import { Hono } from "hono"
import { createFacilitatorRoutes } from "@faremeter/facilitator"
import { createFacilitatorHandler as createSolanaHandler } from "@faremeter/payment-solana/exact"
import { createFacilitatorHandler as createEvmHandler } from "@faremeter/payment-evm/exact"
import { createSolanaRpc } from "@solana/kit"
import { getKeypairFromFile } from "@solana-program/node-helpers"

// Solana
const rpc = createSolanaRpc(process.env.SOLANA_RPC_URL!)
const feePayerKeypair = await getKeypairFromFile(process.env.SOLANA_PAYER_KEYPAIR!)
const solanaMint = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"

// EVM
const chain = { id: 84532, name: "base-sepolia", rpcUrl: process.env.EVM_RPC_URL! }

const handlers = [
  await createSolanaHandler("devnet", rpc, feePayerKeypair, solanaMint),
  await createEvmHandler(chain, process.env.EVM_PRIVATE_KEY!, "USDC"),
]

const app = new Hono()
app.route("/", createFacilitatorRoutes({ handlers }))

export { app }
Each handler implements the FacilitatorHandler interface:
import type { FacilitatorHandler } from "@faremeter/types/facilitator"

interface FacilitatorHandler {
  getSupported?: () => Promise<x402SupportedKind>[]
  getRequirements: (req: x402PaymentRequirements[]) => Promise<x402PaymentRequirements[]>
  handleVerify?: (requirements, payment) => Promise<x402VerifyResponse | null>
  handleSettle: (requirements, payment) => Promise<x402SettleResponse | null>
}
Handlers return null for payment schemes they do not support, allowing the facilitator to route to the correct handler.

Environment configuration

Facilitator handlers typically need:
  • RPC endpoint URLs for each chain
  • Private keys for transaction submission (the facilitator submits transactions on behalf of clients)
  • Token contract addresses
Configure these via environment variables:
SOLANA_RPC_URL=https://api.devnet.solana.com
SOLANA_PAYER_KEYPAIR=~/.config/solana/facilitator.json
EVM_RPC_URL=https://sepolia.base.org
EVM_PRIVATE_KEY=0x...

Facilitator endpoints

EndpointMethodPurpose
/acceptsPOSTEnriches payment requirements with facilitator-specific fields.
/verifyPOSTVerifies a payment without settling.
/settlePOSTVerifies and settles a payment on-chain. Returns transaction hash.
/supportedGETLists supported schemes, networks, and assets.

Further reading