> ## Documentation Index
> Fetch the complete documentation index at: https://armory.sh/llms.txt
> Use this file to discover all available pages before exploring further.

> Payment middleware for Hono

# @armory-sh/middleware-hono

Accept crypto payments in your Hono API with a single middleware function.

## Installation

```bash theme={null}
# npm
npm install @armory-sh/middleware-hono

# yarn
yarn add @armory-sh/middleware-hono

# pnpm
pnpm add @armory-sh/middleware-hono

# bun
bun add @armory-sh/middleware-hono
```

## Quick Start

```typescript theme={null}
import { Hono } from 'hono';
import { acceptPaymentsViaArmory } from '@armory-sh/middleware-hono';

const app = new Hono();

app.use('/api/*', acceptPaymentsViaArmory({
  payTo: '0xYourWalletAddress...',
  amount: '1.0'
}));

app.get('/api/protected', (c) => {
  const payment = c.get('payment');
  return c.json({ message: `Hello ${payment.payerAddress}!` });
});

app.listen(3000);
```

***

## How It Works

The middleware intercepts requests and:

1. Checks for payment headers (`X-Payment` or `X402-PAYMENT`)
2. Verifies the payment signature and amount
3. Stores payment info in the Hono context
4. Calls `next()` if valid, or returns 402 if invalid

***

## Configuration

### Minimal Setup

```typescript theme={null}
acceptPaymentsViaArmory({
  payTo: '0xYourWallet...',  // Your wallet address
  amount: '1.0'              // Amount in tokens (e.g., 1 USDC)
});
```

### All Options

```typescript theme={null}
{
  payTo: string,                           // Your wallet address
  amount: string | bigint,                 // Amount to charge
  token?: string,                          // Token symbol (default: USDC)
  network?: string,                        // Network name (default: base)
  defaultVersion?: 1 | 2                   // Payment version (default: 2)
}
```

***

## Accessing Payment Info

Payment information is stored in the Hono context:

```typescript theme={null}
app.get('/api/user', (c) => {
  const payment = c.get('payment');

  return c.json({
    payer: payment.payerAddress,
    paid: payment.payload.amount,
    token: payment.payload.token
  });
});
```

**Available Properties:**

| Property       | Type             | Description                                   |
| -------------- | ---------------- | --------------------------------------------- |
| `payload`      | `PaymentPayload` | Decoded payment payload                       |
| `payerAddress` | `string`         | Wallet address of the payer                   |
| `version`      | `1 \| 2`         | Payment protocol version                      |
| `verified`     | `true`           | Always true when request reaches your handler |

***

## Response Headers

On successful verification:

```
X-Payment-Verified: true
X-Payer-Address: 0x...
X-Payment-Response: {"status":"verified","payerAddress":"0x...","version":2}
```

***

## Error Responses

### 402 Payment Required

```json theme={null}
{
  "error": "Payment required",
  "requirements": { ... }
}
```

### 402 Verification Failed

```json theme={null}
{
  "error": "Payment verification failed: ..."
}
```

***

## Multi-Network Support

Accept payments across multiple networks and tokens:

```typescript theme={null}
app.use('/api/*', acceptPaymentsViaArmory({
  payTo: '0x...',
  amount: '1.0',
  accept: {
    networks: ['base', 'ethereum', 'polygon'],
    tokens: ['usdc', 'usdt']
  }
}));
```

## Advanced Mix-and-Match Config (Current API)

```typescript theme={null}
import { Hono } from "hono";
import { paymentMiddleware } from "@armory-sh/middleware-hono";

const app = new Hono();

app.use(
  "/api/*",
  paymentMiddleware({
    payTo: "0x1234567890123456789012345678901234567890",
    chains: ["base", "skale-base"],
    tokens: ["usdc", "usdt", "weth", "wbtc"],
    amount: "1.0",
    facilitatorUrl: "https://fallback-facilitator.example",
    facilitatorUrlByChain: {
      base: "https://payai.example",
    },
    facilitatorUrlByToken: {
      base: { usdc: "https://payai.example" },
      "skale-base": {
        usdc: "https://payai.example",
        usdt: "https://kobaru.example",
        weth: "https://kobaru.example",
        wbtc: "https://kobaru.example",
      },
    },
    extensions: {
      bazaar: { info: { input: { sku: "pro-plan" } }, schema: { type: "object" } },
      "sign-in-with-x": { info: { domain: "api.example.com" }, schema: { type: "object" } },
    },
  }),
);
```

If you need fully custom amount-per-requirement combinations, use explicit `requirements`:

```typescript theme={null}
paymentMiddleware({
  requirements: [
    {
      scheme: "exact",
      network: "eip155:8453",
      amount: "1000000",
      asset: "0x833589fCD6eDb6E08f4c7C32D4f71B54bdA02913",
      payTo: "0x1234567890123456789012345678901234567890",
      maxTimeoutSeconds: 300,
    },
    {
      scheme: "exact",
      network: "eip155:1187947933",
      amount: "2500000",
      asset: "0x5f9beea3f6f22be1f4f8efc120f5095f58dbb8a2",
      payTo: "0x1234567890123456789012345678901234567890",
      maxTimeoutSeconds: 300,
    },
  ],
  facilitatorUrlByToken: {
    base: { usdc: "https://payai.example" },
    "skale-base": { usdt: "https://kobaru.example" },
  },
});
```

Extension keys are fail-open filtered by facilitator capability: unsupported keys are automatically omitted from `PAYMENT-REQUIRED`.

***

## Tips

<Tip>
  The `amount` parameter accepts human-readable strings like `"1.0"` for 1 token, or use `bigint` for precise decimal control.
</Tip>

<Note>
  Hono middleware applies to routes that match the path pattern. Use `/api/*` to protect all API routes, or specific paths like `/premium/*` for paid content.
</Note>

<Warning>
  The middleware will return 402 before your handler runs if payment is missing or invalid. Only verified requests reach your route handlers.
</Warning>
