@x402kit/middleware 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# @x402-kit/middleware
|
|
2
|
+
|
|
3
|
+
> One-line Express middleware for HTTP 402 payment gating on Stacks — monetize any API route with STX micropayments.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@x402-kit/middleware)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
`@x402-kit/middleware` wraps the [x402-stacks](https://www.npmjs.com/package/x402-stacks) protocol into a single Express middleware call. Define per-route STX prices in a config object, and every matching request is automatically gated behind an HTTP 402 payment flow — receipt verification, replay protection, and all.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @x402-kit/middleware
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
> **Peer dependency:** requires `express` ≥ 4.
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import express from 'express';
|
|
24
|
+
import { x402Paywall } from '@x402-kit/middleware';
|
|
25
|
+
|
|
26
|
+
const app = express();
|
|
27
|
+
|
|
28
|
+
app.use(x402Paywall({
|
|
29
|
+
prices: {
|
|
30
|
+
'/premium': '0.01 STX',
|
|
31
|
+
'/data': '0.05 STX',
|
|
32
|
+
},
|
|
33
|
+
payTo: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM',
|
|
34
|
+
network: 'testnet',
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
app.get('/premium', (req, res) => {
|
|
38
|
+
res.json({ message: 'Paid premium content' });
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
app.get('/data', (req, res) => {
|
|
42
|
+
res.json({ data: [1, 2, 3] });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
app.get('/', (req, res) => {
|
|
46
|
+
res.send('Free homepage — no payment required');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
app.listen(3000, () => console.log('Listening on :3000'));
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Any request to `/premium` or `/data` will receive an HTTP 402 response unless a valid payment receipt is provided. Routes not listed in `prices` pass through normally.
|
|
53
|
+
|
|
54
|
+
## API Reference
|
|
55
|
+
|
|
56
|
+
### `x402Paywall(options): express.RequestHandler`
|
|
57
|
+
|
|
58
|
+
Returns an Express middleware function.
|
|
59
|
+
|
|
60
|
+
#### `X402Options`
|
|
61
|
+
|
|
62
|
+
| Property | Type | Required | Default | Description |
|
|
63
|
+
|----------|------|----------|---------|-------------|
|
|
64
|
+
| `prices` | `Record<string, string>` | ✅ | — | Map of route paths to STX price strings (e.g. `'0.01 STX'`) |
|
|
65
|
+
| `payTo` | `string` | ✅ | — | Stacks address that receives payments |
|
|
66
|
+
| `network` | `'mainnet' \| 'testnet'` | — | `'testnet'` | Stacks network to use |
|
|
67
|
+
| `facilitatorUrl` | `string` | — | `'https://facilitator.stacksx402.xyz'` | URL of the x402 facilitator service |
|
|
68
|
+
|
|
69
|
+
### How It Works
|
|
70
|
+
|
|
71
|
+
1. An incoming request hits the middleware.
|
|
72
|
+
2. The middleware checks if the request path has a price defined in `prices`.
|
|
73
|
+
3. **If yes** — it delegates to the `x402-stacks` `paymentMiddleware`, which returns an HTTP 402 with payment instructions or validates the payment receipt attached to the request.
|
|
74
|
+
4. **If no** — the request passes through to the next handler untouched.
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
Client Request
|
|
78
|
+
│
|
|
79
|
+
▼
|
|
80
|
+
x402Paywall middleware
|
|
81
|
+
│
|
|
82
|
+
├── Path in prices? ──▶ paymentMiddleware (x402-stacks)
|
|
83
|
+
│ │
|
|
84
|
+
│ ├── Valid receipt? → next()
|
|
85
|
+
│ └── No receipt? → 402 response
|
|
86
|
+
│
|
|
87
|
+
└── Path NOT in prices? ──▶ next()
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Examples
|
|
91
|
+
|
|
92
|
+
### Per-endpoint pricing
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
app.use(x402Paywall({
|
|
96
|
+
prices: {
|
|
97
|
+
'/api/sentiment': '0.001 STX', // cheap
|
|
98
|
+
'/api/summarize': '0.01 STX', // moderate
|
|
99
|
+
'/api/train': '1.00 STX', // expensive
|
|
100
|
+
},
|
|
101
|
+
payTo: 'SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKNRV9EJ7',
|
|
102
|
+
network: 'mainnet',
|
|
103
|
+
}));
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Custom facilitator
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
app.use(x402Paywall({
|
|
110
|
+
prices: { '/data': '0.01 STX' },
|
|
111
|
+
payTo: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM',
|
|
112
|
+
facilitatorUrl: 'https://my-facilitator.example.com',
|
|
113
|
+
}));
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### With existing middleware stack
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
app.use(cors());
|
|
120
|
+
app.use(express.json());
|
|
121
|
+
app.use(x402Paywall({
|
|
122
|
+
prices: { '/premium': '0.01 STX' },
|
|
123
|
+
payTo: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM',
|
|
124
|
+
}));
|
|
125
|
+
// Routes defined below are gated
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Requirements
|
|
129
|
+
|
|
130
|
+
- **Node.js** ≥ 18
|
|
131
|
+
- **Express** ≥ 4
|
|
132
|
+
- **x402-stacks** ≥ 2 (installed automatically)
|
|
133
|
+
|
|
134
|
+
## Related Packages
|
|
135
|
+
|
|
136
|
+
| Package | Description |
|
|
137
|
+
|---------|-------------|
|
|
138
|
+
| [`@x402-kit/cli`](https://www.npmjs.com/package/@x402-kit/cli) | Scaffold tool for generating x402-kit projects |
|
|
139
|
+
| [`@x402-kit/agent-client`](https://www.npmjs.com/package/@x402-kit/agent-client) | Autonomous agent client that pays for API access automatically |
|
|
140
|
+
| [`x402-stacks`](https://www.npmjs.com/package/x402-stacks) | Core x402 protocol SDK for Stacks |
|
|
141
|
+
|
|
142
|
+
## Contributing
|
|
143
|
+
|
|
144
|
+
Contributions are welcome! Please see the [main repository](https://github.com/x402-kit/x402-kit) for development setup and guidelines.
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
export interface X402Options {
|
|
3
|
+
prices: Record<string, string>;
|
|
4
|
+
payTo: string;
|
|
5
|
+
network?: 'mainnet' | 'testnet';
|
|
6
|
+
facilitatorUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* x402Paywall middleware for Express.
|
|
10
|
+
* Protects routes based on the provided prices map.
|
|
11
|
+
*/
|
|
12
|
+
export declare function x402Paywall(options: X402Options): (req: Request, res: Response, next: NextFunction) => Promise<void | Response<any, Record<string, any>>> | undefined;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.x402Paywall = x402Paywall;
|
|
4
|
+
const x402_stacks_1 = require("x402-stacks");
|
|
5
|
+
/**
|
|
6
|
+
* x402Paywall middleware for Express.
|
|
7
|
+
* Protects routes based on the provided prices map.
|
|
8
|
+
*/
|
|
9
|
+
function x402Paywall(options) {
|
|
10
|
+
const { prices, payTo, network = 'testnet', facilitatorUrl = 'https://facilitator.stacksx402.xyz' } = options;
|
|
11
|
+
// Pre-calculate microSTX prices to avoid parsing on every request
|
|
12
|
+
const microPrices = {};
|
|
13
|
+
for (const [path, priceStr] of Object.entries(prices)) {
|
|
14
|
+
const amount = parseFloat(priceStr.split(' ')[0]);
|
|
15
|
+
microPrices[path] = (0, x402_stacks_1.STXtoMicroSTX)(amount);
|
|
16
|
+
}
|
|
17
|
+
return (req, res, next) => {
|
|
18
|
+
const amount = microPrices[req.path];
|
|
19
|
+
if (amount !== undefined) {
|
|
20
|
+
// Use x402-stacks paymentMiddleware for the specific amount
|
|
21
|
+
return (0, x402_stacks_1.paymentMiddleware)({
|
|
22
|
+
amount,
|
|
23
|
+
payTo,
|
|
24
|
+
network,
|
|
25
|
+
facilitatorUrl
|
|
26
|
+
})(req, res, next);
|
|
27
|
+
}
|
|
28
|
+
// No price defined for this route, proceed
|
|
29
|
+
next();
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAcA,kCA0BC;AAvCD,6CAA+D;AAS/D;;;GAGG;AACH,SAAgB,WAAW,CAAC,OAAoB;IAC9C,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,SAAS,EAAE,cAAc,GAAG,oCAAoC,EAAE,GAAG,OAAO,CAAC;IAE9G,kEAAkE;IAClE,MAAM,WAAW,GAAoC,EAAE,CAAC;IACxD,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,WAAW,CAAC,IAAI,CAAC,GAAG,IAAA,2BAAa,EAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACzD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAErC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,4DAA4D;YAC5D,OAAO,IAAA,+BAAiB,EAAC;gBACvB,MAAM;gBACN,KAAK;gBACL,OAAO;gBACP,cAAc;aACf,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACrB,CAAC;QAED,2CAA2C;QAC3C,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@x402kit/middleware",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "One-line Express middleware for HTTP 402 payment gating on Stacks — monetize any API route with STX micropayments",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "x402-kit contributors",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/x402-kit/x402-kit.git",
|
|
10
|
+
"directory": "packages/middleware"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/x402-kit/x402-kit#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/x402-kit/x402-kit/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"x402",
|
|
18
|
+
"stacks",
|
|
19
|
+
"http-402",
|
|
20
|
+
"express",
|
|
21
|
+
"middleware",
|
|
22
|
+
"payments",
|
|
23
|
+
"paywall",
|
|
24
|
+
"api-monetization",
|
|
25
|
+
"micropayments",
|
|
26
|
+
"web3",
|
|
27
|
+
"blockchain",
|
|
28
|
+
"stx"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"main": "dist/index.js",
|
|
34
|
+
"types": "dist/index.d.ts",
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"README.md"
|
|
38
|
+
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsc",
|
|
44
|
+
"test": "jest",
|
|
45
|
+
"prepublishOnly": "npm run build"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"express": ">=4.0.0"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"x402-stacks": "^2.0.1"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"express": "^4.18.2",
|
|
55
|
+
"@types/express": "^4.17.25",
|
|
56
|
+
"jest": "^29.7.0",
|
|
57
|
+
"ts-jest": "^29.1.1",
|
|
58
|
+
"typescript": "^5.3.3"
|
|
59
|
+
}
|
|
60
|
+
}
|