create-x402-app 0.1.2 → 0.1.4

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.
Files changed (60) hide show
  1. package/dist/index.js +54 -4
  2. package/package.json +2 -2
  3. package/templates/backend-express/README.md +56 -0
  4. package/templates/backend-express/env.example +8 -0
  5. package/templates/backend-express/gitignore +4 -0
  6. package/templates/backend-express/package.json +23 -0
  7. package/templates/backend-express/src/index.ts +79 -0
  8. package/templates/backend-express/tsconfig.json +18 -0
  9. package/templates/backend-hono/README.md +57 -0
  10. package/templates/backend-hono/env.example +8 -0
  11. package/templates/backend-hono/gitignore +4 -0
  12. package/templates/backend-hono/package.json +21 -0
  13. package/templates/backend-hono/src/index.ts +75 -0
  14. package/templates/backend-hono/tsconfig.json +18 -0
  15. package/templates/fullstack-express/README.md +308 -0
  16. package/templates/fullstack-express/_env.example +11 -0
  17. package/templates/fullstack-express/_gitignore +46 -0
  18. package/templates/fullstack-express/eslint.config.mjs +18 -0
  19. package/templates/fullstack-express/next-env.d.ts +6 -0
  20. package/templates/fullstack-express/next.config.ts +7 -0
  21. package/templates/fullstack-express/package.json +33 -0
  22. package/templates/fullstack-express/postcss.config.mjs +7 -0
  23. package/templates/fullstack-express/public/X402.png +0 -0
  24. package/templates/fullstack-express/src/app/api/info/route.ts +14 -0
  25. package/templates/fullstack-express/src/app/api/premium/route.ts +52 -0
  26. package/templates/fullstack-express/src/app/api/weather/route.ts +103 -0
  27. package/templates/fullstack-express/src/app/favicon.ico +0 -0
  28. package/templates/fullstack-express/src/app/globals.css +82 -0
  29. package/templates/fullstack-express/src/app/layout.tsx +42 -0
  30. package/templates/fullstack-express/src/app/page.tsx +511 -0
  31. package/templates/fullstack-express/src/components/grain-overlay.tsx +11 -0
  32. package/templates/fullstack-express/src/components/magnetic-button.tsx +90 -0
  33. package/templates/fullstack-express/src/components/ui/blur-fade.tsx +81 -0
  34. package/templates/fullstack-express/src/components/ui/magic-card.tsx +103 -0
  35. package/templates/fullstack-express/src/lib/utils.ts +6 -0
  36. package/templates/fullstack-express/src/types/ethereum.d.ts +11 -0
  37. package/templates/fullstack-express/tsconfig.json +34 -0
  38. package/templates/fullstack-hono/README.md +308 -0
  39. package/templates/fullstack-hono/_env.example +11 -0
  40. package/templates/fullstack-hono/_gitignore +46 -0
  41. package/templates/fullstack-hono/eslint.config.mjs +18 -0
  42. package/templates/fullstack-hono/next-env.d.ts +6 -0
  43. package/templates/fullstack-hono/next.config.ts +7 -0
  44. package/templates/fullstack-hono/package.json +33 -0
  45. package/templates/fullstack-hono/postcss.config.mjs +7 -0
  46. package/templates/fullstack-hono/public/X402.png +0 -0
  47. package/templates/fullstack-hono/src/app/api/info/route.ts +14 -0
  48. package/templates/fullstack-hono/src/app/api/premium/route.ts +52 -0
  49. package/templates/fullstack-hono/src/app/api/weather/route.ts +103 -0
  50. package/templates/fullstack-hono/src/app/favicon.ico +0 -0
  51. package/templates/fullstack-hono/src/app/globals.css +82 -0
  52. package/templates/fullstack-hono/src/app/layout.tsx +42 -0
  53. package/templates/fullstack-hono/src/app/page.tsx +511 -0
  54. package/templates/fullstack-hono/src/components/grain-overlay.tsx +11 -0
  55. package/templates/fullstack-hono/src/components/magnetic-button.tsx +90 -0
  56. package/templates/fullstack-hono/src/components/ui/blur-fade.tsx +81 -0
  57. package/templates/fullstack-hono/src/components/ui/magic-card.tsx +103 -0
  58. package/templates/fullstack-hono/src/lib/utils.ts +6 -0
  59. package/templates/fullstack-hono/src/types/ethereum.d.ts +11 -0
  60. package/templates/fullstack-hono/tsconfig.json +34 -0
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ var require_package = __commonJS({
31
31
  "package.json"(exports2, module2) {
32
32
  module2.exports = {
33
33
  name: "create-x402-app",
34
- version: "0.1.2",
34
+ version: "0.1.4",
35
35
  description: "Create a new x402 pay-per-request API project",
36
36
  keywords: [
37
37
  "x402",
@@ -57,7 +57,7 @@ var require_package = __commonJS({
57
57
  },
58
58
  files: [
59
59
  "dist",
60
- "template"
60
+ "templates"
61
61
  ],
62
62
  scripts: {
63
63
  build: "tsup",
@@ -97,6 +97,53 @@ var packageJson = require_package();
97
97
  function getTemplateDir(projectType, framework) {
98
98
  return `${projectType}-${framework}`;
99
99
  }
100
+ function getTemplatesDirectory() {
101
+ const possiblePaths = [
102
+ import_path.default.join(__dirname, "..", "templates"),
103
+ // When installed as package (most common)
104
+ import_path.default.join(__dirname, "templates")
105
+ // When running from source
106
+ ];
107
+ for (const templatePath of possiblePaths) {
108
+ if (import_fs_extra.default.existsSync(templatePath)) {
109
+ return templatePath;
110
+ }
111
+ }
112
+ let currentDir = __dirname;
113
+ let attempts = 0;
114
+ const maxAttempts = 10;
115
+ while (attempts < maxAttempts) {
116
+ const pkgPath = import_path.default.join(currentDir, "package.json");
117
+ if (import_fs_extra.default.existsSync(pkgPath)) {
118
+ try {
119
+ const pkg = import_fs_extra.default.readJsonSync(pkgPath);
120
+ if (pkg.name === "create-x402-app") {
121
+ const templatesPath = import_path.default.join(currentDir, "templates");
122
+ if (import_fs_extra.default.existsSync(templatesPath)) {
123
+ return templatesPath;
124
+ }
125
+ }
126
+ } catch (e) {
127
+ }
128
+ }
129
+ const parentDir = import_path.default.dirname(currentDir);
130
+ if (parentDir === currentDir) {
131
+ break;
132
+ }
133
+ currentDir = parentDir;
134
+ attempts++;
135
+ }
136
+ const npxPaths = [
137
+ import_path.default.join(process.env.HOME || process.env.USERPROFILE || "", ".npm", "_npx", "templates"),
138
+ import_path.default.join(process.cwd(), "node_modules", "create-x402-app", "templates")
139
+ ];
140
+ for (const templatePath of npxPaths) {
141
+ if (import_fs_extra.default.existsSync(templatePath)) {
142
+ return templatePath;
143
+ }
144
+ }
145
+ throw new Error(`Could not find templates directory. Searched from: ${__dirname}`);
146
+ }
100
147
  function showBanner() {
101
148
  return new Promise((resolve) => {
102
149
  import_figlet.default.text("x402", {
@@ -288,15 +335,18 @@ async function main() {
288
335
  }
289
336
  const spinner = (0, import_ora.default)("Creating project...").start();
290
337
  try {
291
- const templatePath = import_path.default.join(__dirname, "..", "templates", templateName);
338
+ const templatesDir = getTemplatesDirectory();
339
+ const templatePath = import_path.default.join(templatesDir, templateName);
292
340
  if (!import_fs_extra.default.existsSync(templatePath)) {
293
341
  spinner.fail(`Template not found: ${templateName}`);
294
342
  console.log(import_chalk.default.yellow(`
295
343
  Available templates:`));
296
- const templatesDir = import_path.default.join(__dirname, "..", "templates");
297
344
  if (import_fs_extra.default.existsSync(templatesDir)) {
298
345
  const templates = import_fs_extra.default.readdirSync(templatesDir);
299
346
  templates.forEach((t) => console.log(import_chalk.default.gray(` \u2022 ${t}`)));
347
+ } else {
348
+ console.log(import_chalk.default.red(`Templates directory not found at: ${templatesDir}`));
349
+ console.log(import_chalk.default.yellow(`__dirname: ${__dirname}`));
300
350
  }
301
351
  process.exit(1);
302
352
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-x402-app",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Create a new x402 pay-per-request API project",
5
5
  "keywords": [
6
6
  "x402",
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "files": [
28
28
  "dist",
29
- "template"
29
+ "templates"
30
30
  ],
31
31
  "scripts": {
32
32
  "build": "tsup",
@@ -0,0 +1,56 @@
1
+ # x402 Backend - Express
2
+
3
+ A robust API server with pay-per-request endpoints using x402 on Mantle Network.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Install dependencies
9
+ npm install
10
+
11
+ # Configure environment
12
+ cp .env.example .env
13
+ # Edit .env with your App ID from https://mantle-x402.vercel.app
14
+
15
+ # Start development server
16
+ npm run dev
17
+ ```
18
+
19
+ ## Endpoints
20
+
21
+ | Endpoint | Price | Description |
22
+ |----------|-------|-------------|
23
+ | `GET /` | Free | API information |
24
+ | `GET /api/premium` | 0.001 MNT | Premium content |
25
+ | `GET /api/weather` | 0.0005 MNT | Weather data |
26
+
27
+ ## Adding New Paid Endpoints
28
+
29
+ ```typescript
30
+ import { x402Express } from 'x402-mantle-sdk/server'
31
+
32
+ app.get(
33
+ '/api/my-endpoint',
34
+ x402Express({ price: '0.01', token: 'MNT', testnet: true }),
35
+ (req, res) => {
36
+ // Access payment info via req.x402
37
+ console.log('Payment verified:', req.x402.transactionHash)
38
+ res.json({ data: 'Your premium content' })
39
+ }
40
+ )
41
+ ```
42
+
43
+ ## Production
44
+
45
+ ```bash
46
+ # Build
47
+ npm run build
48
+
49
+ # Start production server
50
+ npm start
51
+ ```
52
+
53
+ ## Learn More
54
+
55
+ - [x402 Documentation](https://mantle-x402.vercel.app)
56
+ - [Express Documentation](https://expressjs.com)
@@ -0,0 +1,8 @@
1
+ # x402 Configuration
2
+ # Get your App ID from: https://mantle-x402.vercel.app
3
+
4
+ X402_APP_ID=your_app_id_here
5
+ X402_PLATFORM_URL=https://mantle-x402.vercel.app
6
+
7
+ # Server
8
+ PORT=3000
@@ -0,0 +1,4 @@
1
+ node_modules
2
+ dist
3
+ .env
4
+ *.log
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "x402-backend-express",
3
+ "version": "1.0.0",
4
+ "description": "x402 API server with Express",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "tsx watch src/index.ts",
8
+ "build": "tsc",
9
+ "start": "node dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "cors": "^2.8.5",
13
+ "express": "^4.21.0",
14
+ "x402-mantle-sdk": "^0.2.3"
15
+ },
16
+ "devDependencies": {
17
+ "@types/cors": "^2.8.17",
18
+ "@types/express": "^4.17.21",
19
+ "@types/node": "^20.0.0",
20
+ "tsx": "^4.7.0",
21
+ "typescript": "^5.0.0"
22
+ }
23
+ }
@@ -0,0 +1,79 @@
1
+ import express from 'express'
2
+ import cors from 'cors'
3
+ import { x402Express } from 'x402-mantle-sdk/server'
4
+
5
+ const app = express()
6
+
7
+ // Middleware
8
+ app.use(cors())
9
+ app.use(express.json())
10
+
11
+ // Free endpoint - API info
12
+ app.get('/', (req, res) => {
13
+ res.json({
14
+ name: 'x402 API',
15
+ version: '1.0.0',
16
+ endpoints: {
17
+ info: 'GET / - API information (free)',
18
+ premium: 'GET /api/premium - Premium content (0.001 MNT)',
19
+ weather: 'GET /api/weather - Weather data (0.0005 MNT)',
20
+ },
21
+ network: 'mantle-sepolia',
22
+ docs: 'https://mantle-x402.vercel.app',
23
+ })
24
+ })
25
+
26
+ // Premium endpoint - requires 0.001 MNT
27
+ app.get(
28
+ '/api/premium',
29
+ x402Express({ price: '0.001', token: 'MNT', testnet: true }),
30
+ (req, res) => {
31
+ res.json({
32
+ success: true,
33
+ message: 'Premium content unlocked!',
34
+ data: {
35
+ secret: 'This is premium data that required payment.',
36
+ timestamp: new Date().toISOString(),
37
+ },
38
+ })
39
+ }
40
+ )
41
+
42
+ // Weather endpoint - requires 0.0005 MNT
43
+ app.get(
44
+ '/api/weather',
45
+ x402Express({ price: '0.0005', token: 'MNT', testnet: true }),
46
+ (req, res) => {
47
+ res.json({
48
+ success: true,
49
+ weather: {
50
+ location: 'San Francisco, CA',
51
+ temperature: 72,
52
+ unit: 'fahrenheit',
53
+ conditions: 'Sunny',
54
+ humidity: 45,
55
+ wind: '10 mph NW',
56
+ },
57
+ })
58
+ }
59
+ )
60
+
61
+ // Start server
62
+ const port = Number(process.env.PORT) || 3000
63
+
64
+ app.listen(port, () => {
65
+ console.log(`
66
+ ╔═══════════════════════════════════════════════════════════╗
67
+ ║ x402 Express Server ║
68
+ ╠═══════════════════════════════════════════════════════════╣
69
+ ║ Server running on http://localhost:${port} ║
70
+ ║ ║
71
+ ║ Endpoints: ║
72
+ ║ GET / - API info (free) ║
73
+ ║ GET /api/premium - Premium content (0.001 MNT) ║
74
+ ║ GET /api/weather - Weather data (0.0005 MNT) ║
75
+ ║ ║
76
+ ║ Network: mantle-sepolia (testnet) ║
77
+ ╚═══════════════════════════════════════════════════════════╝
78
+ `)
79
+ })
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true
15
+ },
16
+ "include": ["src/**/*"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }
@@ -0,0 +1,57 @@
1
+ # x402 Backend - Hono
2
+
3
+ A lightweight API server with pay-per-request endpoints using x402 on Mantle Network.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Install dependencies
9
+ npm install
10
+
11
+ # Configure environment
12
+ cp .env.example .env
13
+ # Edit .env with your App ID from https://mantle-x402.vercel.app
14
+
15
+ # Start development server
16
+ npm run dev
17
+ ```
18
+
19
+ ## Endpoints
20
+
21
+ | Endpoint | Price | Description |
22
+ |----------|-------|-------------|
23
+ | `GET /` | Free | API information |
24
+ | `GET /api/premium` | 0.001 MNT | Premium content |
25
+ | `GET /api/weather` | 0.0005 MNT | Weather data |
26
+
27
+ ## Adding New Paid Endpoints
28
+
29
+ ```typescript
30
+ import { x402 } from 'x402-mantle-sdk/server'
31
+
32
+ // Add middleware before the route handler
33
+ app.use('/api/my-endpoint', x402({
34
+ price: '0.01',
35
+ token: 'MNT',
36
+ testnet: true
37
+ }))
38
+
39
+ app.get('/api/my-endpoint', (c) => {
40
+ return c.json({ data: 'Your premium content' })
41
+ })
42
+ ```
43
+
44
+ ## Production
45
+
46
+ ```bash
47
+ # Build
48
+ npm run build
49
+
50
+ # Start production server
51
+ npm start
52
+ ```
53
+
54
+ ## Learn More
55
+
56
+ - [x402 Documentation](https://mantle-x402.vercel.app)
57
+ - [Hono Documentation](https://hono.dev)
@@ -0,0 +1,8 @@
1
+ # x402 Configuration
2
+ # Get your App ID from: https://mantle-x402.vercel.app
3
+
4
+ X402_APP_ID=your_app_id_here
5
+ X402_PLATFORM_URL=https://mantle-x402.vercel.app
6
+
7
+ # Server
8
+ PORT=3000
@@ -0,0 +1,4 @@
1
+ node_modules
2
+ dist
3
+ .env
4
+ *.log
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "x402-backend-hono",
3
+ "version": "1.0.0",
4
+ "description": "x402 API server with Hono",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "tsx watch src/index.ts",
8
+ "build": "tsc",
9
+ "start": "node dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "@hono/node-server": "^1.13.0",
13
+ "hono": "^4.6.0",
14
+ "x402-mantle-sdk": "^0.2.3"
15
+ },
16
+ "devDependencies": {
17
+ "@types/node": "^20.0.0",
18
+ "tsx": "^4.7.0",
19
+ "typescript": "^5.0.0"
20
+ }
21
+ }
@@ -0,0 +1,75 @@
1
+ import { serve } from '@hono/node-server'
2
+ import { Hono } from 'hono'
3
+ import { cors } from 'hono/cors'
4
+ import { logger } from 'hono/logger'
5
+ import { x402 } from 'x402-mantle-sdk/server'
6
+
7
+ const app = new Hono()
8
+
9
+ // Middleware
10
+ app.use('*', logger())
11
+ app.use('*', cors())
12
+
13
+ // Free endpoint - API info
14
+ app.get('/', (c) => {
15
+ return c.json({
16
+ name: 'x402 API',
17
+ version: '1.0.0',
18
+ endpoints: {
19
+ info: 'GET / - API information (free)',
20
+ premium: 'GET /api/premium - Premium content (0.001 MNT)',
21
+ weather: 'GET /api/weather - Weather data (0.0005 MNT)',
22
+ },
23
+ network: 'mantle-sepolia',
24
+ docs: 'https://mantle-x402.vercel.app',
25
+ })
26
+ })
27
+
28
+ // Premium endpoint - requires 0.001 MNT
29
+ app.use('/api/premium', x402({ price: '0.001', token: 'MNT', testnet: true }))
30
+ app.get('/api/premium', (c) => {
31
+ return c.json({
32
+ success: true,
33
+ message: 'Premium content unlocked!',
34
+ data: {
35
+ secret: 'This is premium data that required payment.',
36
+ timestamp: new Date().toISOString(),
37
+ },
38
+ })
39
+ })
40
+
41
+ // Weather endpoint - requires 0.0005 MNT
42
+ app.use('/api/weather', x402({ price: '0.0005', token: 'MNT', testnet: true }))
43
+ app.get('/api/weather', (c) => {
44
+ return c.json({
45
+ success: true,
46
+ weather: {
47
+ location: 'San Francisco, CA',
48
+ temperature: 72,
49
+ unit: 'fahrenheit',
50
+ conditions: 'Sunny',
51
+ humidity: 45,
52
+ wind: '10 mph NW',
53
+ },
54
+ })
55
+ })
56
+
57
+ // Start server
58
+ const port = Number(process.env.PORT) || 3000
59
+
60
+ console.log(`
61
+ ╔═══════════════════════════════════════════════════════════╗
62
+ ║ x402 Hono Server ║
63
+ ╠═══════════════════════════════════════════════════════════╣
64
+ ║ Server running on http://localhost:${port} ║
65
+ ║ ║
66
+ ║ Endpoints: ║
67
+ ║ GET / - API info (free) ║
68
+ ║ GET /api/premium - Premium content (0.001 MNT) ║
69
+ ║ GET /api/weather - Weather data (0.0005 MNT) ║
70
+ ║ ║
71
+ ║ Network: mantle-sepolia (testnet) ║
72
+ ╚═══════════════════════════════════════════════════════════╝
73
+ `)
74
+
75
+ serve({ fetch: app.fetch, port })
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true
15
+ },
16
+ "include": ["src/**/*"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }