> ## 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 Bun servers

# @armory-sh/middleware-bun

Accept crypto payments in your Bun HTTP server with a single function call.

## Installation

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

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

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

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

## Quick Start

```typescript theme={null}
import { createBunMiddleware } from '@armory-sh/middleware-bun';

const middleware = createBunMiddleware({
  payTo: '0xYourWalletAddress...',
  amount: '1.0'
});

Bun.serve({
  port: 3000,
  fetch: async (req) => {
    const result = await middleware(req);

    // If middleware returns a response, payment failed/required
    if (result) return result;

    // Payment verified — handle your request
    return new Response(JSON.stringify({ data: 'protected content' }));
  }
});
```

***

## How It Works

The middleware intercepts incoming requests and:

1. Checks for payment headers (`X-Payment` or `X402-PAYMENT`)
2. Verifies the payment signature and amount
3. Returns `null` if valid (allowing your handler to proceed)
4. Returns a `Response` with 402 status if payment is missing or invalid

***

## Configuration

### Required Options

```typescript theme={null}
{
  payTo: string,     // Your wallet address
  amount: string | bigint  // Amount to charge
}
```

### Settlement Modes

Control how payments are settled after verification:

```typescript theme={null}
const middleware = createBunMiddleware({
  payTo: '0x...',
  amount: '1.0',
  settlementMode: 'verify'  // | 'settle' | 'async'
});
```

| Mode     | Description                                  |
| -------- | -------------------------------------------- |
| `verify` | Verify only, don't settle (good for testing) |
| `settle` | Verify and settle on-chain before responding |
| `async`  | Return immediately, settle in background     |

### Verification Backend

Use your deployed verification backend in production.

***

## Response Format

On successful payment verification, the middleware returns a `Response` with:

**Headers:**

* `X-Payment-Verified: true`
* `X-Payer-Address: 0x...`

**Body:**

```json theme={null}
{
  "verified": true,
  "payerAddress": "0x...",
  "version": 2
}
```

***

## Error Responses

### 402 Payment Required

No payment header was provided.

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

### 402 Verification Failed

Payment signature or amount was invalid.

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

### 400 Settlement Failed

Settlement mode was `settle` but on-chain transaction failed.

```json theme={null}
{
  "error": "Settlement failed"
}
```

***

## Tips

<Tip>
  For development and testing, use `settlementMode: 'verify'` to skip on-chain settlement while still verifying payment signatures.
</Tip>

<Note>
  The `amount` can be specified as a human-readable string like `"1.0"` for 1 token, or as a `bigint` for precise control over decimals.
</Note>

<Warning>
  Always validate the `payTo` address matches your wallet. The middleware does not check if the address is valid or belongs to you.
</Warning>

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

Use `paymentMiddleware` for per-token/per-network facilitator routing and extension-aware challenge headers:

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

const middleware = 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" } },
  },
});
```

For fully custom amount-per-combination behavior, pass 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" },
  },
});
```

Unsupported extension keys are auto-ignored (fail-open) per facilitator `/supported` capability response.
