openzoo 0.51.2 → 0.51.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.
- package/README.md +2 -0
- package/bin/openzoo.js +26 -8
- package/lib/chatgpt.js +328 -0
- package/lib/proxy.js +8 -7
- package/lib/stripeOnramp.js +9 -3
- package/package.json +2 -2
- package/transmute/README.md +42 -9
- package/transmute/lib/build.js +72 -2
- package/transmute/lib/cli.js +73 -17
- package/transmute/lib/compile/bytecode.js +591 -0
- package/transmute/lib/compile/hostids.js +11 -0
- package/transmute/lib/compile/index.js +16 -3
- package/transmute/lib/deploy.js +149 -1
- package/transmute/lib/gateway.js +14 -8
- package/transmute/lib/hub.js +13 -3
- package/transmute/lib/solana.js +67 -21
- package/transmute/lib/wire.js +42 -1
- package/transmute/prebuilt/zoo_vm.v0.so +0 -0
- package/transmute/runtime/zoo-host/examples/vmrun.rs +43 -0
- package/transmute/runtime/zoo-host/src/assets.rs +53 -10
- package/transmute/runtime/zoo-host/src/ctx.rs +15 -0
- package/transmute/runtime/zoo-host/src/helpers.rs +245 -0
- package/transmute/runtime/zoo-host/src/kv.rs +29 -8
- package/transmute/runtime/zoo-host/src/lib.rs +13 -0
- package/transmute/runtime/zoo-host/src/site.rs +94 -0
- package/transmute/runtime/zoo-host/src/vm.rs +902 -0
- package/transmute/runtime/zoo-vm/Cargo.lock +596 -0
- package/transmute/runtime/zoo-vm/Cargo.toml +23 -0
- package/transmute/runtime/zoo-vm/src/lib.rs +92 -0
- package/transmute/site/package.json +6 -0
- package/transmute/site/public/index.html +4 -4
package/transmute/lib/build.js
CHANGED
|
@@ -251,8 +251,10 @@ export async function build(root = '.', opts = {}) {
|
|
|
251
251
|
log(`reading ${root} → ${deployment.source}${deployment.framework ? ` (${deployment.framework})` : ''}: ${deployment.functions.length} function(s), ${deployment.staticFiles.length} static file(s)`);
|
|
252
252
|
for (const n of deployment.notes) { log(`note: ${n}`); notes.push(n); }
|
|
253
253
|
|
|
254
|
+
const target = opts.target === 'shared' ? 'shared' : 'program';
|
|
254
255
|
const transmute = opts.transmute || await loadTransmute();
|
|
255
|
-
const result = await transmute(deployment, { name, runtimePath, arch: opts.arch, root, outDir });
|
|
256
|
+
const result = await transmute(deployment, { name, runtimePath, arch: opts.arch, root, outDir, target });
|
|
257
|
+
if (target === 'shared') return buildShared({ root, outDir, zooDir, deployment, name, result, notes, log, opts });
|
|
256
258
|
if (!result || !result.crate || !result.crate['Cargo.toml'] || !result.crate['src/lib.rs']) throw new Error('transmute() returned no crate (expected {crate:{"Cargo.toml","src/lib.rs"}, manifest, report})');
|
|
257
259
|
const manifest = { name, ...(result.manifest || {}) };
|
|
258
260
|
if (!manifest.version) manifest.version = 1;
|
|
@@ -295,7 +297,7 @@ export async function build(root = '.', opts = {}) {
|
|
|
295
297
|
const soSize = soPath ? fs.statSync(soPath).size : null;
|
|
296
298
|
writeJson(path.join(zooDir, 'build.json'), {
|
|
297
299
|
name, crateName, root, outDir, arch, soPath, soSize, soName: soNameFor(crateName), builtAt: new Date().toISOString(),
|
|
298
|
-
runtimePath, cargo: cargo ? { ok: cargo.ok, missing: !!cargo.missing } : { skipped: true },
|
|
300
|
+
runtimePath, cargo: cargo ? { ok: cargo.ok, missing: !!cargo.missing } : { skipped: true }, target: 'program',
|
|
299
301
|
});
|
|
300
302
|
|
|
301
303
|
// Cost sheet.
|
|
@@ -309,3 +311,71 @@ export async function build(root = '.', opts = {}) {
|
|
|
309
311
|
log(`next: openzoo-transmute deploy ${path.relative(process.cwd(), outDir) || outDir} --cluster <localnet|devnet|mainnet>`);
|
|
310
312
|
return { outDir, zooDir, crateDir, manifest, report, soPath, arch, costEstimate, deployment, notes, staticPlan };
|
|
311
313
|
}
|
|
314
|
+
|
|
315
|
+
// ---------------------------------------------------------------- shared runtime
|
|
316
|
+
|
|
317
|
+
/** Bytes of the site account the shared runtime creates per site. */
|
|
318
|
+
export const SITE_ACCOUNT_BYTES = 66;
|
|
319
|
+
|
|
320
|
+
/** Rent for a shared-runtime site: site account + code asset + assets + manifest (no program). */
|
|
321
|
+
export async function estimateSharedCost({ staticFiles = [], codeSize = 0, manifestBytes = 0, connection = null }) {
|
|
322
|
+
const est = await estimateCost({ staticFiles, soSize: null, manifestBytes, connection });
|
|
323
|
+
est.items = est.items.filter((i) => i.kind !== 'program');
|
|
324
|
+
const rent = async (n) => { if (connection) { try { return await connection.getMinimumBalanceForRentExemption(n); } catch {} } return (ACCOUNT_OVERHEAD_BYTES + n) * LAMPORTS_PER_BYTE; };
|
|
325
|
+
const codeBytes = accountBytesFor('asset', codeSize, 'application/x-zoo-bytecode');
|
|
326
|
+
const extra = [
|
|
327
|
+
{ label: 'site account (shared runtime)', kind: 'site', bytes: SITE_ACCOUNT_BYTES, lamports: await rent(SITE_ACCOUNT_BYTES) },
|
|
328
|
+
{ label: `/.zoo/code.bin (bytecode = ${codeSize.toLocaleString()} B)`, kind: 'asset', bytes: codeBytes, lamports: await rent(codeBytes) },
|
|
329
|
+
];
|
|
330
|
+
for (const it of extra) it.sol = it.lamports / LAMPORTS_PER_SOL;
|
|
331
|
+
est.items = [...extra, ...est.items];
|
|
332
|
+
est.lamports += extra.reduce((n, i) => n + i.lamports, 0);
|
|
333
|
+
est.sol = est.lamports / LAMPORTS_PER_SOL;
|
|
334
|
+
est.feeLamports = 5000 * (2 + Math.ceil(codeSize / 900) + staticFiles.reduce((n, f) => n + 1 + Math.ceil(f.size / 900), 0) + 2);
|
|
335
|
+
est.feeSol = est.feeLamports / LAMPORTS_PER_SOL;
|
|
336
|
+
est.totalLamports = est.lamports + est.transientLamports + est.feeLamports;
|
|
337
|
+
est.totalSol = est.totalLamports / LAMPORTS_PER_SOL;
|
|
338
|
+
est.unknownProgram = false;
|
|
339
|
+
est.shared = true;
|
|
340
|
+
return est;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** `build --target shared`: bytecode module instead of a crate; nothing to compile. */
|
|
344
|
+
async function buildShared({ root, outDir, zooDir, deployment, name, result, notes, log, opts }) {
|
|
345
|
+
if (!result || !result.code || !result.code.length) throw new Error('transmute() returned no bytecode module for --target shared');
|
|
346
|
+
const manifest = { name, ...(result.manifest || {}), target: 'shared' };
|
|
347
|
+
if (!manifest.version) manifest.version = 1;
|
|
348
|
+
if (!manifest.framework) manifest.framework = deployment.framework;
|
|
349
|
+
if (!Array.isArray(manifest.routes)) manifest.routes = [];
|
|
350
|
+
if (!Array.isArray(manifest.static)) manifest.static = deployment.staticFiles.map((f) => ({ path: f.path, contentType: f.contentType, size: f.size }));
|
|
351
|
+
if (!manifest.config) manifest.config = deployment.config;
|
|
352
|
+
const runtime = opts.runtime || process.env.OPENZOO_VM_PROGRAM || null;
|
|
353
|
+
if (runtime) manifest.runtime = runtime;
|
|
354
|
+
const report = { eligible: [], ineligible: [], warnings: [], ...(result.report || {}) };
|
|
355
|
+
|
|
356
|
+
fs.rmSync(path.join(zooDir, 'crate'), { recursive: true, force: true });
|
|
357
|
+
fs.mkdirSync(zooDir, { recursive: true });
|
|
358
|
+
const codePath = path.join(zooDir, 'code.bin');
|
|
359
|
+
fs.writeFileSync(codePath, result.code);
|
|
360
|
+
const byPath = new Map(deployment.staticFiles.map((f) => [f.path, f]));
|
|
361
|
+
const staticPlan = manifest.static.map((s) => ({ ...s, file: byPath.get(s.path)?.file || s.file || null }));
|
|
362
|
+
writeJson(path.join(zooDir, 'manifest.json'), manifest);
|
|
363
|
+
writeJson(path.join(zooDir, 'report.json'), report);
|
|
364
|
+
writeJson(path.join(zooDir, 'static-plan.json'), staticPlan);
|
|
365
|
+
const codeSize = result.code.length;
|
|
366
|
+
writeJson(path.join(zooDir, 'build.json'), { name, root, outDir, target: 'shared', codePath, codeSize, runtime, builtAt: new Date().toISOString(), cargo: { skipped: true } });
|
|
367
|
+
log(`wrote ${path.relative(process.cwd(), zooDir) || zooDir}/{code.bin (${codeSize.toLocaleString()} B bytecode), manifest.json, report.json, static-plan.json}`);
|
|
368
|
+
log(`functions: ${report.eligible.length} eligible, ${report.ineligible.length} ineligible${report.warnings.length ? `, ${report.warnings.length} warning(s)` : ''}`);
|
|
369
|
+
for (const i of report.ineligible) log(` ✗ ${i.name}: ${i.reason}${i.file ? ` (${path.relative(root, i.file)}${i.line ? ':' + i.line : ''})` : ''}`);
|
|
370
|
+
for (const w of report.warnings) log(` ! ${typeof w === 'string' ? w : w.message || JSON.stringify(w)}`);
|
|
371
|
+
if (!runtime) { const n = 'no --runtime given: pass --runtime <zoo-vm program id> (or OPENZOO_VM_PROGRAM) at deploy time'; notes.push(n); log(`note: ${n}`); }
|
|
372
|
+
|
|
373
|
+
const connection = opts.connection !== undefined ? opts.connection : await probeConnection(opts.cluster || 'localnet');
|
|
374
|
+
const manifestBytes = Buffer.byteLength(JSON.stringify({ ...manifest, runtime: 'x'.repeat(44), site: 'x'.repeat(44), deployedAt: new Date().toISOString() }));
|
|
375
|
+
const costEstimate = await estimateSharedCost({ staticFiles: staticPlan, codeSize, manifestBytes, connection });
|
|
376
|
+
log('');
|
|
377
|
+
log(formatCostTable(costEstimate));
|
|
378
|
+
log('');
|
|
379
|
+
log(`next: openzoo-transmute deploy ${path.relative(process.cwd(), outDir) || outDir} --cluster mainnet${runtime ? '' : ' --runtime <id>'}`);
|
|
380
|
+
return { outDir, zooDir, crateDir: null, manifest, report, soPath: null, codePath, codeSize, arch: null, target: 'shared', costEstimate, deployment, notes, staticPlan };
|
|
381
|
+
}
|
package/transmute/lib/cli.js
CHANGED
|
@@ -14,20 +14,25 @@ import path from 'node:path';
|
|
|
14
14
|
import { PublicKey } from '@solana/web3.js';
|
|
15
15
|
import { readDeployment } from './vercel.js';
|
|
16
16
|
import { build } from './build.js';
|
|
17
|
-
import { deploy, resolveOutDir, clusterLabel } from './deploy.js';
|
|
17
|
+
import { deploy, deployRuntime, resolveOutDir, clusterLabel } from './deploy.js';
|
|
18
18
|
import { startGateway, DEFAULT_PORT } from './gateway.js';
|
|
19
19
|
import { startHub, DEFAULT_HUB_PORT } from './hub.js';
|
|
20
|
-
import { connect, getProgramInfo, readManifest } from './solana.js';
|
|
20
|
+
import { connect, getProgramInfo, getSiteInfo, readManifest } from './solana.js';
|
|
21
21
|
import { loadWallet, rpcUrl } from './wallet.js';
|
|
22
22
|
import { MANIFEST_PATH } from './wire.js';
|
|
23
23
|
|
|
24
24
|
export const USAGE = `openzoo-transmute — Vercel app → Solana program + asset accounts
|
|
25
25
|
|
|
26
26
|
usage:
|
|
27
|
-
openzoo-transmute build [dir] [--out .zoo-out] [--name <crate>] [--arch v0|v3] [--cluster <c>] [--skip-cargo]
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
openzoo-transmute
|
|
27
|
+
openzoo-transmute build [dir] [--target shared|program] [--out .zoo-out] [--name <crate>] [--arch v0|v3] [--cluster <c>] [--skip-cargo]
|
|
28
|
+
--target shared (default): bytecode for the shared zoo-vm runtime — a site is data accounts only (≈0.05–0.1 SOL)
|
|
29
|
+
--target program: your own Pinocchio program per site (≈1 SOL+)
|
|
30
|
+
openzoo-transmute deploy [dir|outDir] [--cluster mainnet|devnet|localnet|<url>] [--keypair <path>] [--yes] [--runtime <zoo-vm id>]
|
|
31
|
+
[--program <id>] [--concurrency 4] [--skip-assets] [--force] [--headroom 1.5]
|
|
32
|
+
openzoo-transmute serve <siteId|programId> [--runtime <zoo-vm id>] [--cluster <c>] [--port ${DEFAULT_PORT}] [--keypair <path>] [--host 127.0.0.1] [--quiet]
|
|
33
|
+
openzoo-transmute runtime deploy [--cluster <c>] [--keypair <path>] [--yes] [--program-keypair zoo-vm-keypair.json] [--so <path>]
|
|
34
|
+
deploy (or upgrade) the shared zoo-vm runtime once per cluster
|
|
35
|
+
openzoo-transmute runtime status <zoo-vm id> [--cluster <c>]
|
|
31
36
|
openzoo-transmute hub [--cluster mainnet] [--port 8080] [--host 0.0.0.0] [--public-url <https://…>]
|
|
32
37
|
hosted explorer for EVERY program on the cluster (/s/<programId>), read-only
|
|
33
38
|
openzoo-transmute inspect [dir] print the Vercel model + eligibility report
|
|
@@ -35,7 +40,7 @@ usage:
|
|
|
35
40
|
openzoo-transmute help
|
|
36
41
|
|
|
37
42
|
clusters: mainnet (default, needs --yes to deploy), devnet, testnet, localnet, or an RPC URL.
|
|
38
|
-
env: OPENZOO_CLUSTER, OPENZOO_RPC (mainnet RPC), OPENZOO_KEYPAIR / OPENZOO_WALLET (signer).
|
|
43
|
+
env: OPENZOO_CLUSTER, OPENZOO_RPC (mainnet RPC), OPENZOO_KEYPAIR / OPENZOO_WALLET (signer), OPENZOO_VM_PROGRAM (shared runtime id).
|
|
39
44
|
`;
|
|
40
45
|
|
|
41
46
|
/** `--k v`, `--k=v`, `--flag`, `--no-flag`; everything else is positional. */
|
|
@@ -114,26 +119,49 @@ async function tryTransmute(deployment) {
|
|
|
114
119
|
}
|
|
115
120
|
}
|
|
116
121
|
|
|
122
|
+
export const DEFAULT_TARGET = 'shared';
|
|
123
|
+
|
|
124
|
+
/** `--runtime` is the zoo-vm program id (shared) — or, for `--target program`, a zoo-host checkout path. */
|
|
125
|
+
function runtimeFlag(f) {
|
|
126
|
+
const v = f.runtime;
|
|
127
|
+
if (typeof v !== 'string') return { runtime: process.env.OPENZOO_VM_PROGRAM || null, runtimePath: f.runtimePath || undefined };
|
|
128
|
+
if (fs.existsSync(v) && fs.existsSync(path.join(v, 'Cargo.toml'))) return { runtime: process.env.OPENZOO_VM_PROGRAM || null, runtimePath: v };
|
|
129
|
+
new PublicKey(v);
|
|
130
|
+
return { runtime: v, runtimePath: f.runtimePath || undefined };
|
|
131
|
+
}
|
|
132
|
+
|
|
117
133
|
async function cmdBuild(p, f, log) {
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
134
|
+
const target = f.target || process.env.OPENZOO_TARGET || DEFAULT_TARGET;
|
|
135
|
+
if (!['shared', 'program'].includes(target)) throw new Error(`--target must be shared or program (got ${target})`);
|
|
136
|
+
const { runtime, runtimePath } = runtimeFlag(f);
|
|
137
|
+
const r = await build(p[0] || '.', { out: f.out, name: f.name, arch: f.arch, cluster: f.cluster, target, runtime, runtimePath, skipCargo: !!f.skipCargo, log });
|
|
138
|
+
if (f.json) log(JSON.stringify({ outDir: r.outDir, target: r.target || 'program', soPath: r.soPath, codePath: r.codePath || null, codeSize: r.codeSize || null, arch: r.arch, report: r.report, costEstimate: { sol: r.costEstimate.sol, totalSol: r.costEstimate.totalSol, source: r.costEstimate.source } }, null, 2));
|
|
120
139
|
return r.report.ineligible.length && !r.report.eligible.length && r.manifest.routes.length === 0 && r.deployment.functions.length ? 2 : 0;
|
|
121
140
|
}
|
|
122
141
|
|
|
123
142
|
async function cmdDeploy(p, f, log) {
|
|
124
|
-
const
|
|
143
|
+
const { runtime } = runtimeFlag(f);
|
|
144
|
+
const r = await deploy({ outDir: p[0] || '.', cluster: f.cluster, keypair: f.keypair, programId: f.program, runtime, yes: !!f.yes, concurrency: f.concurrency ? Number(f.concurrency) : undefined, skipAssets: !!f.skipAssets, force: !!f.force, headroom: f.headroom, log });
|
|
125
145
|
if (f.json) log(JSON.stringify(r, null, 2));
|
|
126
146
|
return 0;
|
|
127
147
|
}
|
|
128
148
|
|
|
129
149
|
async function cmdServe(p, f, log) {
|
|
130
150
|
let programId = p[0];
|
|
151
|
+
let { runtime } = runtimeFlag(f);
|
|
131
152
|
if (!programId) {
|
|
132
153
|
// Fall back to the last deploy in ./ or ./.zoo-out.
|
|
133
|
-
try {
|
|
134
|
-
|
|
154
|
+
try {
|
|
155
|
+
const d = JSON.parse(fs.readFileSync(path.join(resolveOutDir('.'), '.zoo', 'deploy.json'), 'utf8'));
|
|
156
|
+
programId = d.target === 'shared' ? d.site : d.programId;
|
|
157
|
+
if (d.target === 'shared' && !runtime) runtime = d.runtime;
|
|
158
|
+
} catch { /* none */ }
|
|
159
|
+
if (!programId) throw new Error('usage: serve <siteId|programId> [--runtime <zoo-vm id>] (no .zoo/deploy.json found to infer it from)');
|
|
135
160
|
}
|
|
136
161
|
new PublicKey(programId); // validate
|
|
162
|
+
// Shared runtime: the positional is the site id, the program is zoo-vm.
|
|
163
|
+
let site = null;
|
|
164
|
+
if (runtime) { site = programId; programId = runtime; }
|
|
137
165
|
let keypair = null, walletPath = null;
|
|
138
166
|
if (f.keypair !== false) {
|
|
139
167
|
try { const w = loadWallet({ keypair: typeof f.keypair === 'string' ? f.keypair : undefined }); keypair = w.keypair; walletPath = w.path; }
|
|
@@ -142,10 +170,10 @@ async function cmdServe(p, f, log) {
|
|
|
142
170
|
const port = f.port != null ? Number(f.port) : DEFAULT_PORT;
|
|
143
171
|
const host = f.host || '127.0.0.1';
|
|
144
172
|
if (keypair && !/^(127\.0\.0\.1|localhost|::1|\[::1\])$/.test(host)) log(`warning: binding ${host} with a signer: anyone who can reach this gateway can send transactions paid by ${keypair.publicKey.toBase58()}; use --no-keypair unless that is intended`);
|
|
145
|
-
const gw = await startGateway({ programId, cluster: f.cluster, port, host, keypair, log, quiet: !!f.quiet });
|
|
173
|
+
const gw = await startGateway({ programId, site, cluster: f.cluster, port, host, keypair, log, quiet: !!f.quiet });
|
|
146
174
|
const m = gw.state.manifest;
|
|
147
175
|
log(`openzoo-transmute gateway → ${gw.url}/ (explorer ${gw.url}/.zoo/, manifest ${gw.url}${MANIFEST_PATH})`);
|
|
148
|
-
log(`program ${programId} on ${gw.state.cluster} · ${m.routes.length} function(s), ${m.static ? m.static.length : '?'} asset(s) · signer ${keypair ? keypair.publicKey.toBase58() + (walletPath ? ` (${walletPath})` : '') : 'none (reads only)'}`);
|
|
176
|
+
log(`${site ? `site ${site} on runtime ${programId}` : `program ${programId}`} on ${gw.state.cluster} · ${m.routes.length} function(s), ${m.static ? m.static.length : '?'} asset(s) · signer ${keypair ? keypair.publicKey.toBase58() + (walletPath ? ` (${walletPath})` : '') : 'none (reads only)'}`);
|
|
149
177
|
for (const r of m.routes) log(` ${(r.methods && r.methods.length ? r.methods.join('|') : 'ANY').padEnd(16)} ${r.routePath}`);
|
|
150
178
|
const stop = () => gw.close().then(() => process.exit(0));
|
|
151
179
|
process.once('SIGINT', stop);
|
|
@@ -165,10 +193,24 @@ async function cmdInspect(p, f, log) {
|
|
|
165
193
|
}
|
|
166
194
|
|
|
167
195
|
async function cmdStatus(p, f, log) {
|
|
168
|
-
if (!p[0]) throw new Error('usage: status <programId> [--cluster <c>]');
|
|
169
|
-
const
|
|
196
|
+
if (!p[0]) throw new Error('usage: status <siteId|programId> [--runtime <zoo-vm id>] [--cluster <c>]');
|
|
197
|
+
const { runtime } = runtimeFlag(f);
|
|
170
198
|
const rpc = rpcUrl(f.cluster);
|
|
171
199
|
const connection = connect(rpc);
|
|
200
|
+
if (runtime) {
|
|
201
|
+
const site = new PublicKey(p[0]);
|
|
202
|
+
const [info, manifest] = await Promise.all([getSiteInfo(connection, new PublicKey(runtime), site), readManifest(connection, new PublicKey(runtime), site).catch(() => null)]);
|
|
203
|
+
const out = { site: site.toBase58(), runtime, cluster: clusterLabel(f.cluster), rpc: rpc.replace(/\?.*$/, ''), exists: info.exists, authority: info.authority ? info.authority.toBase58() : null, account: info.pda.toBase58(), manifest: manifest ? { name: manifest.name, routes: manifest.routes?.length ?? 0, static: manifest.static?.length ?? 0, deployedAt: manifest.deployedAt } : null };
|
|
204
|
+
if (f.json) { log(JSON.stringify(out, null, 2)); return info.exists ? 0 : 1; }
|
|
205
|
+
log(`site ${out.site} on runtime ${runtime} (${out.cluster})`);
|
|
206
|
+
if (!info.exists) { log('status NOT DEPLOYED'); return 1; }
|
|
207
|
+
log(`authority ${out.authority}`);
|
|
208
|
+
log(`account ${out.account}`);
|
|
209
|
+
if (manifest) { log(`manifest ${manifest.name || ''} · ${out.manifest.routes} function(s), ${out.manifest.static} asset(s) · deployed ${manifest.deployedAt || '?'}`); for (const r of manifest.routes || []) log(` ${(r.methods && r.methods.length ? r.methods.join('|') : 'ANY').padEnd(16)} ${r.routePath}`); }
|
|
210
|
+
else log(`manifest none at ${MANIFEST_PATH}`);
|
|
211
|
+
return 0;
|
|
212
|
+
}
|
|
213
|
+
const programId = new PublicKey(p[0]);
|
|
172
214
|
const [info, slot, manifest] = await Promise.all([getProgramInfo(connection, programId), connection.getSlot('confirmed'), readManifest(connection, programId).catch(() => null)]);
|
|
173
215
|
const out = {
|
|
174
216
|
programId: programId.toBase58(), cluster: clusterLabel(f.cluster), rpc: rpc.replace(/\?.*$/, ''), slot,
|
|
@@ -215,13 +257,27 @@ async function cmdHub(p, f, log) {
|
|
|
215
257
|
return 0;
|
|
216
258
|
}
|
|
217
259
|
|
|
260
|
+
async function cmdRuntime(p, f, log) {
|
|
261
|
+
const sub = p[0];
|
|
262
|
+
if (sub === 'deploy') {
|
|
263
|
+
const r = await deployRuntime({ cluster: f.cluster, keypair: f.keypair, yes: !!f.yes, programKeypair: f.programKeypair, so: f.so, headroom: f.headroom, log });
|
|
264
|
+
if (f.json) log(JSON.stringify(r, null, 2));
|
|
265
|
+
return 0;
|
|
266
|
+
}
|
|
267
|
+
if (sub === 'status') {
|
|
268
|
+
if (!p[1]) throw new Error('usage: runtime status <zoo-vm id> [--cluster <c>]');
|
|
269
|
+
return cmdStatus([p[1]], { ...f, runtime: undefined }, log);
|
|
270
|
+
}
|
|
271
|
+
throw new Error('usage: runtime deploy|status');
|
|
272
|
+
}
|
|
273
|
+
|
|
218
274
|
export async function run(argv = process.argv.slice(2), io = {}) {
|
|
219
275
|
const log = io.log ?? console.log;
|
|
220
276
|
const error = io.error ?? console.error;
|
|
221
277
|
const { cmd, positionals, flags } = parseArgs(argv);
|
|
222
278
|
if (flags.version) { log(JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version); return 0; }
|
|
223
279
|
if (flags.help || cmd === 'help' || cmd === '--help') { log(USAGE); return 0; }
|
|
224
|
-
const commands = { build: cmdBuild, deploy: cmdDeploy, serve: cmdServe, inspect: cmdInspect, status: cmdStatus, hub: cmdHub };
|
|
280
|
+
const commands = { build: cmdBuild, deploy: cmdDeploy, serve: cmdServe, inspect: cmdInspect, status: cmdStatus, hub: cmdHub, runtime: cmdRuntime };
|
|
225
281
|
const fn = commands[cmd];
|
|
226
282
|
if (!fn) { error(`unknown command: ${cmd}\n`); error(USAGE); process.exitCode = 1; return 1; }
|
|
227
283
|
try {
|