@tallypay/server
v0.0.3
Published
Server middleware for x402 payment gating with lifecycle tracing
Readme
@tallypay/server
Express and Hono middleware for HTTP 402 payment gating with optional TallyPay lifecycle tracing. Works with any facilitator that exposes verify/settle-style HTTP endpoints—TallyPay is the observability layer, not the payment rail.
Install
npm install @tallypay/serverPeer dependencies (install the one you use):
- Express —
express≥ 4 - Hono —
hono≥ 4
@tallypay/core is pulled in automatically as a dependency.
Express
import express from "express";
import { tallypay } from "@tallypay/server/express";
const app = express();
app.use(
"/api/premium",
tallypay({
apiKey: "tp_live_...", // optional: enables trace collection
facilitatorUrl: "https://your-facilitator.example",
payTo: "0xYourMerchantAddress",
price: "10000", // smallest units — match your facilitator’s expectations
network: "eip155:8453",
asset: "USDC",
description: "Premium API access",
}),
);
app.get("/api/premium", (_req, res) => {
res.json({ ok: true });
});Import path: @tallypay/server/express.
Hono
import { Hono } from "hono";
import { tallypay } from "@tallypay/server/hono";
const app = new Hono();
app.use("/api/premium/*", tallypay({
apiKey: "tp_live_...",
facilitatorUrl: "https://your-facilitator.example",
payTo: "0xYourMerchantAddress",
price: "10000",
network: "eip155:8453",
asset: "USDC",
}));
app.get("/api/premium/data", (c) => c.json({ ok: true }));Import path: @tallypay/server/hono.
Config (TallyPayConfig)
| Field | Required | Description |
|--------|----------|-------------|
| facilitatorUrl | yes | Base URL for your facilitator (middleware calls {url}/verify and {url}/settle with the raw payment-signature body). |
| payTo | yes | Recipient address (or identifier your facilitator expects). |
| price | yes | Amount string (convention depends on facilitator/network). |
| network | yes | e.g. eip155:8453. |
| asset | yes | e.g. USDC. |
| apiKey | no | TallyPay API key; if omitted, payment gating still works—traces are not sent. |
| collectorUrl | no | Override for the trace collector URL. |
| description | no | Shown in payment requirements. |
Behaviour
- No
payment-signatureheader → 402 withpayment-requiredheader + JSON body; emits402_ISSUEDwhen tracing is on. - With signature → POST to facilitator verify, then settle; emits lifecycle events (
VERIFY_*,SETTLE_*,PAYMENT_COMPLETEorPAYMENT_ERROR). - Tracing is fire-and-forget: collector failures do not block the response path.
Adjust facilitator request/response shapes if your provider differs—the middleware assumes JSON responses compatible with { valid, reason? } and { settled, txHash? } for verify/settle.
Testing
From the monorepo root (builds @tallypay/core first via Turbo):
pnpm --filter @tallypay/server testIntegration tests use supertest (Express) and Hono’s app.request() with a mocked global fetch for the facilitator.
License
MIT. Source code will be published on GitHub at launch; until then see tallypay.dev.
