run402 1.8.1 → 1.9.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/lib/agent.mjs +4 -22
- package/lib/apps.mjs +8 -30
- package/lib/config.mjs +20 -26
- package/lib/deploy.mjs +12 -31
- package/lib/image.mjs +4 -17
- package/lib/init.mjs +3 -3
- package/lib/message.mjs +4 -22
- package/lib/paid-fetch.mjs +27 -0
- package/lib/projects.mjs +13 -36
- package/lib/sites.mjs +5 -23
- package/lib/tier.mjs +1 -21
- package/package.json +1 -1
package/lib/agent.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { existsSync } from "fs";
|
|
1
|
+
import { API, walletAuthHeaders } from "./config.mjs";
|
|
3
2
|
|
|
4
3
|
const HELP = `run402 agent — Manage agent identity
|
|
5
4
|
|
|
@@ -24,32 +23,15 @@ async function contact(args) {
|
|
|
24
23
|
if (args[i] === "--webhook" && args[i + 1]) webhook = args[++i];
|
|
25
24
|
}
|
|
26
25
|
if (!name) { console.error(JSON.stringify({ status: "error", message: "Missing --name <name>" })); process.exit(1); }
|
|
27
|
-
|
|
28
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const wallet = readWallet();
|
|
33
|
-
const { privateKeyToAccount } = await import("viem/accounts");
|
|
34
|
-
const { createPublicClient, http } = await import("viem");
|
|
35
|
-
const { baseSepolia } = await import("viem/chains");
|
|
36
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
37
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
38
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
39
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
40
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
41
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
42
|
-
const client = new x402Client();
|
|
43
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
44
|
-
const fetchPaid = wrapFetchWithPayment(fetch, client);
|
|
26
|
+
const authHeaders = await walletAuthHeaders();
|
|
45
27
|
|
|
46
28
|
const body = { name };
|
|
47
29
|
if (email) body.email = email;
|
|
48
30
|
if (webhook) body.webhook = webhook;
|
|
49
31
|
|
|
50
|
-
const res = await
|
|
32
|
+
const res = await fetch(`${API}/agent/v1/contact`, {
|
|
51
33
|
method: "POST",
|
|
52
|
-
headers: { "Content-Type": "application/json" },
|
|
34
|
+
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
53
35
|
body: JSON.stringify(body),
|
|
54
36
|
});
|
|
55
37
|
const data = await res.json();
|
package/lib/apps.mjs
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { findProject, readWallet, loadProjects, saveProjects, API, WALLET_FILE, PROJECTS_FILE } from "./config.mjs";
|
|
3
|
-
import { mkdirSync, writeFileSync } from "fs";
|
|
1
|
+
import { findProject, API, walletAuthHeaders, saveProject } from "./config.mjs";
|
|
4
2
|
|
|
5
3
|
const HELP = `run402 apps — Browse and manage the app marketplace
|
|
6
4
|
|
|
@@ -49,31 +47,14 @@ async function fork(versionId, name, args) {
|
|
|
49
47
|
if (args[i] === "--tier" && args[i + 1]) opts.tier = args[++i];
|
|
50
48
|
if (args[i] === "--subdomain" && args[i + 1]) opts.subdomain = args[++i];
|
|
51
49
|
}
|
|
52
|
-
|
|
53
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
54
|
-
process.exit(1);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const wallet = readWallet();
|
|
58
|
-
const { privateKeyToAccount } = await import("viem/accounts");
|
|
59
|
-
const { createPublicClient, http } = await import("viem");
|
|
60
|
-
const { baseSepolia } = await import("viem/chains");
|
|
61
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
62
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
63
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
64
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
65
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
66
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
67
|
-
const client = new x402Client();
|
|
68
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
69
|
-
const fetchPaid = wrapFetchWithPayment(fetch, client);
|
|
50
|
+
const authHeaders = await walletAuthHeaders();
|
|
70
51
|
|
|
71
52
|
const body = { version_id: versionId, name };
|
|
72
53
|
if (opts.subdomain) body.subdomain = opts.subdomain;
|
|
73
54
|
|
|
74
|
-
const res = await
|
|
55
|
+
const res = await fetch(`${API}/fork/v1`, {
|
|
75
56
|
method: "POST",
|
|
76
|
-
headers: { "Content-Type": "application/json" },
|
|
57
|
+
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
77
58
|
body: JSON.stringify(body),
|
|
78
59
|
});
|
|
79
60
|
const data = await res.json();
|
|
@@ -81,15 +62,12 @@ async function fork(versionId, name, args) {
|
|
|
81
62
|
|
|
82
63
|
// Save project credentials locally
|
|
83
64
|
if (data.project_id) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
project_id: data.project_id, anon_key: data.anon_key, service_key: data.service_key,
|
|
65
|
+
saveProject(data.project_id, {
|
|
66
|
+
anon_key: data.anon_key, service_key: data.service_key,
|
|
87
67
|
tier: data.tier, lease_expires_at: data.lease_expires_at,
|
|
88
|
-
site_url: data.site_url || data.subdomain_url,
|
|
68
|
+
site_url: data.site_url || data.subdomain_url,
|
|
69
|
+
deployed_at: new Date().toISOString(),
|
|
89
70
|
});
|
|
90
|
-
const dir = PROJECTS_FILE.replace(/\/[^/]+$/, "");
|
|
91
|
-
mkdirSync(dir, { recursive: true });
|
|
92
|
-
writeFileSync(PROJECTS_FILE, JSON.stringify(projects, null, 2), { mode: 0o600 });
|
|
93
71
|
}
|
|
94
72
|
console.log(JSON.stringify(data, null, 2));
|
|
95
73
|
}
|
package/lib/config.mjs
CHANGED
|
@@ -1,43 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Run402 config loader —
|
|
3
|
-
*
|
|
2
|
+
* Run402 config loader — thin wrapper over core/ shared modules.
|
|
3
|
+
* Adds CLI-specific behavior: process.exit() on errors.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
6
|
+
import { getApiBase, getConfigDir, getKeystorePath, getWalletPath } from "../../core/dist/config.js";
|
|
7
|
+
import { readWallet as coreReadWallet, saveWallet as coreSaveWallet } from "../../core/dist/wallet.js";
|
|
8
|
+
import { getWalletAuthHeaders } from "../../core/dist/wallet-auth.js";
|
|
9
|
+
import { loadKeyStore, getProject, saveProject, removeProject, saveKeyStore } from "../../core/dist/keystore.js";
|
|
10
10
|
|
|
11
|
-
export const CONFIG_DIR =
|
|
12
|
-
export const WALLET_FILE =
|
|
13
|
-
export const PROJECTS_FILE =
|
|
14
|
-
export const API =
|
|
11
|
+
export const CONFIG_DIR = getConfigDir();
|
|
12
|
+
export const WALLET_FILE = getWalletPath();
|
|
13
|
+
export const PROJECTS_FILE = getKeystorePath();
|
|
14
|
+
export const API = getApiBase();
|
|
15
15
|
|
|
16
16
|
export function readWallet() {
|
|
17
|
-
|
|
18
|
-
return JSON.parse(readFileSync(WALLET_FILE, "utf-8"));
|
|
17
|
+
return coreReadWallet();
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
export function saveWallet(data) {
|
|
22
|
-
|
|
23
|
-
const tmp = join(CONFIG_DIR, `.wallet.${randomBytes(4).toString("hex")}.tmp`);
|
|
24
|
-
writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 0o600 });
|
|
25
|
-
renameSync(tmp, WALLET_FILE);
|
|
26
|
-
chmodSync(WALLET_FILE, 0o600);
|
|
21
|
+
coreSaveWallet(data);
|
|
27
22
|
}
|
|
28
23
|
|
|
29
|
-
export function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
export function saveProjects(projects) {
|
|
35
|
-
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
36
|
-
writeFileSync(PROJECTS_FILE, JSON.stringify(projects, null, 2), { mode: 0o600 });
|
|
24
|
+
export async function walletAuthHeaders() {
|
|
25
|
+
const headers = getWalletAuthHeaders();
|
|
26
|
+
if (!headers) { console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create" })); process.exit(1); }
|
|
27
|
+
return headers;
|
|
37
28
|
}
|
|
38
29
|
|
|
39
30
|
export function findProject(id) {
|
|
40
|
-
const p =
|
|
31
|
+
const p = getProject(id);
|
|
41
32
|
if (!p) { console.error(`Project ${id} not found in local registry.`); process.exit(1); }
|
|
42
33
|
return p;
|
|
43
34
|
}
|
|
35
|
+
|
|
36
|
+
// Re-export core keystore functions for direct use
|
|
37
|
+
export { loadKeyStore, saveProject, removeProject, saveKeyStore };
|
package/lib/deploy.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readFileSync
|
|
2
|
-
import {
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { API, walletAuthHeaders, saveProject } from "./config.mjs";
|
|
3
3
|
|
|
4
4
|
const HELP = `run402 deploy — Deploy a full-stack app or static site on Run402
|
|
5
5
|
|
|
@@ -39,14 +39,6 @@ async function readStdin() {
|
|
|
39
39
|
return Buffer.concat(chunks).toString("utf-8");
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
function saveProject(project) {
|
|
43
|
-
const projects = loadProjects();
|
|
44
|
-
projects.push({ project_id: project.project_id, anon_key: project.anon_key, service_key: project.service_key, tier: project.tier, lease_expires_at: project.lease_expires_at, site_url: project.site_url || project.subdomain_url, deployed_at: new Date().toISOString() });
|
|
45
|
-
const dir = PROJECTS_FILE.replace(/\/[^/]+$/, "");
|
|
46
|
-
mkdirSync(dir, { recursive: true });
|
|
47
|
-
writeFileSync(PROJECTS_FILE, JSON.stringify(projects, null, 2), { mode: 0o600 });
|
|
48
|
-
}
|
|
49
|
-
|
|
50
42
|
export async function run(args) {
|
|
51
43
|
const opts = { manifest: null };
|
|
52
44
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -54,30 +46,19 @@ export async function run(args) {
|
|
|
54
46
|
if (args[i] === "--manifest" && args[i + 1]) opts.manifest = args[++i];
|
|
55
47
|
}
|
|
56
48
|
|
|
57
|
-
if (!existsSync(WALLET_FILE)) {
|
|
58
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
-
const wallet = readWallet();
|
|
62
49
|
const manifest = opts.manifest ? JSON.parse(readFileSync(opts.manifest, "utf-8")) : JSON.parse(await readStdin());
|
|
63
50
|
|
|
64
|
-
const
|
|
65
|
-
const {
|
|
66
|
-
const { baseSepolia } = await import("viem/chains");
|
|
67
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
68
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
69
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
70
|
-
|
|
71
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
72
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
73
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
74
|
-
const client = new x402Client();
|
|
75
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
76
|
-
const fetchPaid = wrapFetchWithPayment(fetch, client);
|
|
77
|
-
|
|
78
|
-
const res = await fetchPaid(`${API}/deploy/v1`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(manifest) });
|
|
51
|
+
const authHeaders = await walletAuthHeaders();
|
|
52
|
+
const res = await fetch(`${API}/deploy/v1`, { method: "POST", headers: { "Content-Type": "application/json", ...authHeaders }, body: JSON.stringify(manifest) });
|
|
79
53
|
const result = await res.json();
|
|
80
54
|
if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...result })); process.exit(1); }
|
|
81
|
-
|
|
55
|
+
if (result.project_id) {
|
|
56
|
+
saveProject(result.project_id, {
|
|
57
|
+
anon_key: result.anon_key, service_key: result.service_key,
|
|
58
|
+
tier: result.tier, lease_expires_at: result.lease_expires_at,
|
|
59
|
+
site_url: result.site_url || result.subdomain_url,
|
|
60
|
+
deployed_at: new Date().toISOString(),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
82
63
|
console.log(JSON.stringify(result, null, 2));
|
|
83
64
|
}
|
package/lib/image.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { writeFileSync
|
|
2
|
-
import {
|
|
1
|
+
import { writeFileSync } from "fs";
|
|
2
|
+
import { API, WALLET_FILE } from "./config.mjs";
|
|
3
|
+
import { setupPaidFetch } from "./paid-fetch.mjs";
|
|
3
4
|
|
|
4
5
|
const HELP = `run402 image — Generate AI images via x402 micropayments
|
|
5
6
|
|
|
@@ -49,22 +50,8 @@ export async function run(sub, args) {
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
if (!opts.prompt) { console.error(JSON.stringify({ status: "error", message: "Prompt required. Usage: run402 image generate \"your prompt\"" })); process.exit(1); }
|
|
52
|
-
if (!existsSync(WALLET_FILE)) { console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" })); process.exit(1); }
|
|
53
53
|
|
|
54
|
-
const
|
|
55
|
-
const { privateKeyToAccount } = await import("viem/accounts");
|
|
56
|
-
const { createPublicClient, http } = await import("viem");
|
|
57
|
-
const { baseSepolia } = await import("viem/chains");
|
|
58
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
59
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
60
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
61
|
-
|
|
62
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
63
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
64
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
65
|
-
const client = new x402Client();
|
|
66
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
67
|
-
const fetchPaid = wrapFetchWithPayment(fetch, client);
|
|
54
|
+
const fetchPaid = await setupPaidFetch();
|
|
68
55
|
|
|
69
56
|
const res = await fetchPaid(`${API}/generate-image/v1`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ prompt: opts.prompt, aspect: opts.aspect }) });
|
|
70
57
|
const data = await res.json();
|
package/lib/init.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readWallet, saveWallet,
|
|
1
|
+
import { readWallet, saveWallet, loadKeyStore, CONFIG_DIR, WALLET_FILE, API } from "./config.mjs";
|
|
2
2
|
import { mkdirSync } from "fs";
|
|
3
3
|
|
|
4
4
|
const USDC_ABI = [{ name: "balanceOf", type: "function", stateMutability: "view", inputs: [{ name: "account", type: "address" }], outputs: [{ name: "", type: "uint256" }] }];
|
|
@@ -91,8 +91,8 @@ export async function run() {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
// 5. Projects
|
|
94
|
-
const
|
|
95
|
-
line("Projects", `${projects.length} active`);
|
|
94
|
+
const store = loadKeyStore();
|
|
95
|
+
line("Projects", `${Object.keys(store.projects).length} active`);
|
|
96
96
|
|
|
97
97
|
// 6. Next step
|
|
98
98
|
console.log();
|
package/lib/message.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { existsSync } from "fs";
|
|
1
|
+
import { API, walletAuthHeaders } from "./config.mjs";
|
|
3
2
|
|
|
4
3
|
const HELP = `run402 message — Send messages to Run402 developers
|
|
5
4
|
|
|
@@ -16,28 +15,11 @@ Examples:
|
|
|
16
15
|
|
|
17
16
|
async function send(text) {
|
|
18
17
|
if (!text) { console.error(JSON.stringify({ status: "error", message: "Missing message text" })); process.exit(1); }
|
|
19
|
-
|
|
20
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const wallet = readWallet();
|
|
25
|
-
const { privateKeyToAccount } = await import("viem/accounts");
|
|
26
|
-
const { createPublicClient, http } = await import("viem");
|
|
27
|
-
const { baseSepolia } = await import("viem/chains");
|
|
28
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
29
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
30
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
31
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
32
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
33
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
34
|
-
const client = new x402Client();
|
|
35
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
36
|
-
const fetchPaid = wrapFetchWithPayment(fetch, client);
|
|
18
|
+
const authHeaders = await walletAuthHeaders();
|
|
37
19
|
|
|
38
|
-
const res = await
|
|
20
|
+
const res = await fetch(`${API}/message/v1`, {
|
|
39
21
|
method: "POST",
|
|
40
|
-
headers: { "Content-Type": "application/json" },
|
|
22
|
+
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
41
23
|
body: JSON.stringify({ message: text }),
|
|
42
24
|
});
|
|
43
25
|
const data = await res.json();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared x402 payment wrapper for CLI commands that need paid fetch.
|
|
3
|
+
* Uses viem for wallet signing + @x402/fetch for payment wrapping.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readWallet, WALLET_FILE } from "./config.mjs";
|
|
7
|
+
import { existsSync } from "fs";
|
|
8
|
+
|
|
9
|
+
export async function setupPaidFetch() {
|
|
10
|
+
if (!existsSync(WALLET_FILE)) {
|
|
11
|
+
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
const wallet = readWallet();
|
|
15
|
+
const { privateKeyToAccount } = await import("viem/accounts");
|
|
16
|
+
const { createPublicClient, http } = await import("viem");
|
|
17
|
+
const { baseSepolia } = await import("viem/chains");
|
|
18
|
+
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
19
|
+
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
20
|
+
const { toClientEvmSigner } = await import("@x402/evm");
|
|
21
|
+
const account = privateKeyToAccount(wallet.privateKey);
|
|
22
|
+
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
23
|
+
const signer = toClientEvmSigner(account, publicClient);
|
|
24
|
+
const client = new x402Client();
|
|
25
|
+
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
26
|
+
return wrapFetchWithPayment(fetch, client);
|
|
27
|
+
}
|
package/lib/projects.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { findProject,
|
|
2
|
-
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
1
|
+
import { findProject, loadKeyStore, saveProject, removeProject, API, walletAuthHeaders } from "./config.mjs";
|
|
3
2
|
|
|
4
3
|
const HELP = `run402 projects — Manage your deployed Run402 projects
|
|
5
4
|
|
|
@@ -36,26 +35,6 @@ Notes:
|
|
|
36
35
|
- RLS templates: user_owns_rows, public_read, public_read_write
|
|
37
36
|
`;
|
|
38
37
|
|
|
39
|
-
async function setupPaidFetch() {
|
|
40
|
-
if (!existsSync(WALLET_FILE)) {
|
|
41
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
const wallet = readWallet();
|
|
45
|
-
const { privateKeyToAccount } = await import("viem/accounts");
|
|
46
|
-
const { createPublicClient, http } = await import("viem");
|
|
47
|
-
const { baseSepolia } = await import("viem/chains");
|
|
48
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
49
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
50
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
51
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
52
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
53
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
54
|
-
const client = new x402Client();
|
|
55
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
56
|
-
return wrapFetchWithPayment(fetch, client);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
38
|
async function quote() {
|
|
60
39
|
const res = await fetch(`${API}/tiers/v1`);
|
|
61
40
|
const data = await res.json();
|
|
@@ -69,26 +48,23 @@ async function provision(args) {
|
|
|
69
48
|
if (args[i] === "--tier" && args[i + 1]) opts.tier = args[++i];
|
|
70
49
|
if (args[i] === "--name" && args[i + 1]) opts.name = args[++i];
|
|
71
50
|
}
|
|
72
|
-
const
|
|
51
|
+
const authHeaders = await walletAuthHeaders();
|
|
73
52
|
const body = { tier: opts.tier };
|
|
74
53
|
if (opts.name) body.name = opts.name;
|
|
75
|
-
const res = await
|
|
54
|
+
const res = await fetch(`${API}/projects/v1`, {
|
|
76
55
|
method: "POST",
|
|
77
|
-
headers: { "Content-Type": "application/json" },
|
|
56
|
+
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
78
57
|
body: JSON.stringify(body),
|
|
79
58
|
});
|
|
80
59
|
const data = await res.json();
|
|
81
60
|
if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
|
|
82
61
|
// Save project credentials locally
|
|
83
62
|
if (data.project_id) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
63
|
+
saveProject(data.project_id, {
|
|
64
|
+
anon_key: data.anon_key, service_key: data.service_key,
|
|
65
|
+
tier: data.tier, lease_expires_at: data.lease_expires_at,
|
|
66
|
+
deployed_at: new Date().toISOString(),
|
|
88
67
|
});
|
|
89
|
-
const dir = PROJECTS_FILE.replace(/\/[^/]+$/, "");
|
|
90
|
-
mkdirSync(dir, { recursive: true });
|
|
91
|
-
writeFileSync(PROJECTS_FILE, JSON.stringify(projects, null, 2), { mode: 0o600 });
|
|
92
68
|
}
|
|
93
69
|
console.log(JSON.stringify(data, null, 2));
|
|
94
70
|
}
|
|
@@ -107,9 +83,10 @@ async function rls(projectId, template, tablesJson) {
|
|
|
107
83
|
}
|
|
108
84
|
|
|
109
85
|
async function list() {
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
console.log(JSON.stringify(
|
|
86
|
+
const store = loadKeyStore();
|
|
87
|
+
const entries = Object.entries(store.projects);
|
|
88
|
+
if (entries.length === 0) { console.log(JSON.stringify({ status: "ok", projects: [], message: "No projects yet." })); return; }
|
|
89
|
+
console.log(JSON.stringify(entries.map(([id, p]) => ({ project_id: id, tier: p.tier, site_url: p.site_url, lease_expires_at: p.lease_expires_at, deployed_at: p.deployed_at })), null, 2));
|
|
113
90
|
}
|
|
114
91
|
|
|
115
92
|
async function sqlCmd(projectId, query) {
|
|
@@ -144,7 +121,7 @@ async function deleteProject(projectId) {
|
|
|
144
121
|
const p = findProject(projectId);
|
|
145
122
|
const res = await fetch(`${API}/projects/v1/${projectId}`, { method: "DELETE", headers: { "Authorization": `Bearer ${p.service_key}` } });
|
|
146
123
|
if (res.status === 204 || res.ok) {
|
|
147
|
-
|
|
124
|
+
removeProject(projectId);
|
|
148
125
|
console.log(JSON.stringify({ status: "ok", message: `Project ${projectId} deleted.` }));
|
|
149
126
|
} else {
|
|
150
127
|
const data = await res.json().catch(() => ({}));
|
package/lib/sites.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readFileSync
|
|
2
|
-
import {
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { API, walletAuthHeaders } from "./config.mjs";
|
|
3
3
|
|
|
4
4
|
const HELP = `run402 sites — Deploy and manage static sites
|
|
5
5
|
|
|
@@ -53,33 +53,15 @@ async function deploy(args) {
|
|
|
53
53
|
if (args[i] === "--target" && args[i + 1]) opts.target = args[++i];
|
|
54
54
|
}
|
|
55
55
|
if (!opts.name) { console.error(JSON.stringify({ status: "error", message: "Missing --name <name>" })); process.exit(1); }
|
|
56
|
-
if (!existsSync(WALLET_FILE)) {
|
|
57
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
58
|
-
process.exit(1);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
56
|
const manifest = opts.manifest ? JSON.parse(readFileSync(opts.manifest, "utf-8")) : JSON.parse(await readStdin());
|
|
62
57
|
const body = { name: opts.name, files: manifest.files };
|
|
63
58
|
if (opts.project) body.project = opts.project;
|
|
64
59
|
if (opts.target) body.target = opts.target;
|
|
65
60
|
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
const { createPublicClient, http } = await import("viem");
|
|
69
|
-
const { baseSepolia } = await import("viem/chains");
|
|
70
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
71
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
72
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
73
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
74
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
75
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
76
|
-
const client = new x402Client();
|
|
77
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
78
|
-
const fetchPaid = wrapFetchWithPayment(fetch, client);
|
|
79
|
-
|
|
80
|
-
const res = await fetchPaid(`${API}/deployments/v1`, {
|
|
61
|
+
const authHeaders = await walletAuthHeaders();
|
|
62
|
+
const res = await fetch(`${API}/deployments/v1`, {
|
|
81
63
|
method: "POST",
|
|
82
|
-
headers: { "Content-Type": "application/json" },
|
|
64
|
+
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
83
65
|
body: JSON.stringify(body),
|
|
84
66
|
});
|
|
85
67
|
const data = await res.json();
|
package/lib/tier.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readWallet, WALLET_FILE, API } from "./config.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { setupPaidFetch } from "./paid-fetch.mjs";
|
|
3
3
|
|
|
4
4
|
const HELP = `run402 tier — Manage your Run402 tier subscription
|
|
5
5
|
|
|
@@ -24,26 +24,6 @@ Examples:
|
|
|
24
24
|
run402 tier set hobby
|
|
25
25
|
`;
|
|
26
26
|
|
|
27
|
-
async function setupPaidFetch() {
|
|
28
|
-
if (!existsSync(WALLET_FILE)) {
|
|
29
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
30
|
-
process.exit(1);
|
|
31
|
-
}
|
|
32
|
-
const wallet = readWallet();
|
|
33
|
-
const { privateKeyToAccount } = await import("viem/accounts");
|
|
34
|
-
const { createPublicClient, http } = await import("viem");
|
|
35
|
-
const { baseSepolia } = await import("viem/chains");
|
|
36
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
37
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
38
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
39
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
40
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
41
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
42
|
-
const client = new x402Client();
|
|
43
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
44
|
-
return wrapFetchWithPayment(fetch, client);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
27
|
async function status() {
|
|
48
28
|
const w = readWallet();
|
|
49
29
|
if (!w) { console.log(JSON.stringify({ status: "error", message: "No wallet. Run: run402 wallet create" })); process.exit(1); }
|
package/package.json
CHANGED