@4mica/cli 0.2.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/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/index.js +628 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
- package/snapshot.json +100 -0
- package/templates/agent-buyer-node/.env.example +16 -0
- package/templates/agent-buyer-node/README.md +26 -0
- package/templates/agent-buyer-node/_gitignore +6 -0
- package/templates/agent-buyer-node/package.json +19 -0
- package/templates/agent-buyer-node/src/brain.ts +133 -0
- package/templates/agent-buyer-node/src/critic.ts +195 -0
- package/templates/agent-buyer-node/src/pay.ts +54 -0
- package/templates/agent-buyer-node/tsconfig.json +21 -0
- package/templates/agent-seller-express/.env.example +16 -0
- package/templates/agent-seller-express/README.md +26 -0
- package/templates/agent-seller-express/_gitignore +6 -0
- package/templates/agent-seller-express/package.json +22 -0
- package/templates/agent-seller-express/src/brain.ts +121 -0
- package/templates/agent-seller-express/src/comedian.ts +153 -0
- package/templates/agent-seller-express/tsconfig.json +21 -0
- package/templates/buyer-express/.env.example +12 -0
- package/templates/buyer-express/README.md +26 -0
- package/templates/buyer-express/_gitignore +6 -0
- package/templates/buyer-express/package.json +18 -0
- package/templates/buyer-express/src/buyer.ts +82 -0
- package/templates/buyer-express/tsconfig.json +21 -0
- package/templates/buyer-hono/.env.example +12 -0
- package/templates/buyer-hono/README.md +26 -0
- package/templates/buyer-hono/_gitignore +6 -0
- package/templates/buyer-hono/package.json +18 -0
- package/templates/buyer-hono/src/buyer.ts +82 -0
- package/templates/buyer-hono/tsconfig.json +21 -0
- package/templates/buyer-next/.env.example +12 -0
- package/templates/buyer-next/README.md +26 -0
- package/templates/buyer-next/_gitignore +6 -0
- package/templates/buyer-next/package.json +18 -0
- package/templates/buyer-next/src/buyer.ts +82 -0
- package/templates/buyer-next/tsconfig.json +21 -0
- package/templates/seller-express/.env.example +12 -0
- package/templates/seller-express/README.md +26 -0
- package/templates/seller-express/_gitignore +6 -0
- package/templates/seller-express/package.json +22 -0
- package/templates/seller-express/src/server.ts +64 -0
- package/templates/seller-express/tsconfig.json +21 -0
- package/templates/seller-hono/.env.example +12 -0
- package/templates/seller-hono/README.md +26 -0
- package/templates/seller-hono/_gitignore +6 -0
- package/templates/seller-hono/package.json +22 -0
- package/templates/seller-hono/src/server.ts +69 -0
- package/templates/seller-hono/tsconfig.json +21 -0
- package/templates/seller-next/.env.example +12 -0
- package/templates/seller-next/README.md +26 -0
- package/templates/seller-next/_gitignore +6 -0
- package/templates/seller-next/app/api/protected/route.ts +27 -0
- package/templates/seller-next/app/api/session/route.ts +8 -0
- package/templates/seller-next/app/globals.css +556 -0
- package/templates/seller-next/app/icon.svg +5 -0
- package/templates/seller-next/app/layout.tsx +22 -0
- package/templates/seller-next/app/page.tsx +189 -0
- package/templates/seller-next/next.config.mjs +3 -0
- package/templates/seller-next/package.json +25 -0
- package/templates/seller-next/public/logo-light.svg +19 -0
- package/templates/seller-next/public/logo.svg +19 -0
- package/templates/seller-next/scripts/serve.mjs +46 -0
- package/templates/seller-next/tsconfig.json +30 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__PROJECT_NAME__",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "__DESCRIPTION__",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "tsx watch src/server.ts",
|
|
8
|
+
"start": "tsx src/server.ts"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@4mica/sdk": "workspace:*",
|
|
12
|
+
"@4mica/sdk-hono": "workspace:*",
|
|
13
|
+
"@4mica/sdk-node": "workspace:*",
|
|
14
|
+
"@hono/node-server": "^1.13.0",
|
|
15
|
+
"hono": "catalog:"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "catalog:node24",
|
|
19
|
+
"tsx": "catalog:",
|
|
20
|
+
"typescript": "catalog:typescript-latest"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import type { PaywallConfig, PaywallVerifier } from "@4mica/sdk-hono";
|
|
5
|
+
import { paywall } from "@4mica/sdk-hono";
|
|
6
|
+
import { serve } from "@hono/node-server";
|
|
7
|
+
import { Hono } from "hono";
|
|
8
|
+
|
|
9
|
+
const PORT_FILE = join(tmpdir(), "__TMPFILE__");
|
|
10
|
+
|
|
11
|
+
const verifier: PaywallVerifier = {
|
|
12
|
+
async issueGuarantee(payload) {
|
|
13
|
+
console.log("[seller] verifying payment payload:", payload);
|
|
14
|
+
return { claims: "0xdemoClaims", signature: "0xdemoSignature" };
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const PAYWALL_CONFIG: PaywallConfig = {
|
|
19
|
+
payTo: "0x1111111111111111111111111111111111111111",
|
|
20
|
+
asset: "0x0000000000000000000000000000000000000000",
|
|
21
|
+
network: "base-sepolia",
|
|
22
|
+
amount: "1000",
|
|
23
|
+
tabEndpoint: "http://localhost:__PORT__/session",
|
|
24
|
+
description: "Premium market data feed",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const app = new Hono();
|
|
28
|
+
|
|
29
|
+
app.post("/session", (c) =>
|
|
30
|
+
c.json({
|
|
31
|
+
userAddress: "0x2222222222222222222222222222222222222222",
|
|
32
|
+
nextReqId: "0x1",
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
app.use("/premium", paywall(verifier, PAYWALL_CONFIG));
|
|
37
|
+
app.get("/premium", (c) => {
|
|
38
|
+
const guarantee = c.get("paymentGuarantee");
|
|
39
|
+
return c.json({
|
|
40
|
+
ok: true,
|
|
41
|
+
guarantee,
|
|
42
|
+
data: "🔓 premium market data unlocked",
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
function listen(port: number, attemptsLeft = 20) {
|
|
47
|
+
const server = serve({ fetch: app.fetch, port }, (info) => {
|
|
48
|
+
const url = `http://localhost:${info.port}`;
|
|
49
|
+
PAYWALL_CONFIG.tabEndpoint = `${url}/session`;
|
|
50
|
+
writeFileSync(PORT_FILE, url);
|
|
51
|
+
console.log(`[seller-hono] listening on ${url}`);
|
|
52
|
+
console.log(` GET /premium is paywalled — run the buyer to pay for it.`);
|
|
53
|
+
});
|
|
54
|
+
server.on("error", (err: NodeJS.ErrnoException) => {
|
|
55
|
+
if (err.code === "EADDRINUSE" && attemptsLeft > 0) {
|
|
56
|
+
console.log(`[seller-hono] port ${port} in use, trying ${port + 1}…`);
|
|
57
|
+
listen(port + 1, attemptsLeft - 1);
|
|
58
|
+
} else {
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const cleanup = () => rmSync(PORT_FILE, { force: true });
|
|
65
|
+
process.on("exit", cleanup);
|
|
66
|
+
process.on("SIGINT", () => process.exit(0));
|
|
67
|
+
process.on("SIGTERM", () => process.exit(0));
|
|
68
|
+
|
|
69
|
+
listen(Number(process.env.PORT ?? __PORT__));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"lib": [
|
|
7
|
+
"ES2022",
|
|
8
|
+
"DOM"
|
|
9
|
+
],
|
|
10
|
+
"strict": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"noEmit": true,
|
|
14
|
+
"types": [
|
|
15
|
+
"node"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"include": [
|
|
19
|
+
"src"
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# 4Mica runs in DEMO MODE with zero config (mock verifier / demo payment).
|
|
2
|
+
# To go live, swap the mock verifier for createClient() from @4mica/sdk-node
|
|
3
|
+
# and fill these in. Docs: https://4mica.io/docs
|
|
4
|
+
|
|
5
|
+
# 4MICA_WALLET_PRIVATE_KEY=0x...
|
|
6
|
+
# 4MICA_NETWORK=base-sepolia
|
|
7
|
+
# 4MICA_RPC_URL=
|
|
8
|
+
# 4MICA_ETHEREUM_HTTP_RPC_URL=
|
|
9
|
+
# 4MICA_CONTRACT_ADDRESS=
|
|
10
|
+
# 4MICA_ADMIN_API_KEY=
|
|
11
|
+
# 4MICA_BEARER_TOKEN=
|
|
12
|
+
# 4MICA_AUTH_URL=
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# __PROJECT_NAME__
|
|
2
|
+
|
|
3
|
+
__DESCRIPTION__
|
|
4
|
+
|
|
5
|
+
Generated with `4mica init` — part of the [4Mica](https://4mica.io) x402 payment network.
|
|
6
|
+
|
|
7
|
+
## Run (demo mode — no config)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install
|
|
11
|
+
npm run dev
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Demo mode uses a mock verifier and a locally-built payment header, so it runs
|
|
15
|
+
with **zero credentials**. Start this, then run a matching buyer to exercise the 402 → 200 handshake.
|
|
16
|
+
|
|
17
|
+
## Go live
|
|
18
|
+
|
|
19
|
+
Copy `.env.example` → `.env`, fill in your `4MICA_*` credentials, and swap the
|
|
20
|
+
mock verifier for `createClient()` from `@4mica/sdk-node`.
|
|
21
|
+
|
|
22
|
+
## Manage agents & transactions
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
4mica dashboard
|
|
26
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { PaywallConfig, PaywallVerifier } from "@4mica/sdk-next";
|
|
2
|
+
import { withPaywall } from "@4mica/sdk-next";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
|
|
6
|
+
const verifier: PaywallVerifier = {
|
|
7
|
+
async issueGuarantee(payload) {
|
|
8
|
+
console.log("[seller] verifying payment payload:", payload);
|
|
9
|
+
return { claims: "0xdemoClaims", signature: "0xdemoSignature" };
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const PAYWALL_CONFIG: PaywallConfig = {
|
|
14
|
+
payTo: "0x1111111111111111111111111111111111111111",
|
|
15
|
+
asset: "0x0000000000000000000000000000000000000000",
|
|
16
|
+
network: "base-sepolia",
|
|
17
|
+
amount: "1000",
|
|
18
|
+
tabEndpoint: `${process.env.EXAMPLE_BASE_URL ?? "http://localhost:__PORT__"}/api/session`,
|
|
19
|
+
description: "Premium market data feed",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const GET = withPaywall(
|
|
23
|
+
async () =>
|
|
24
|
+
Response.json({ ok: true, data: "🔓 premium market data unlocked" }),
|
|
25
|
+
verifier,
|
|
26
|
+
PAYWALL_CONFIG,
|
|
27
|
+
);
|