@clanker-chain/clanker-cli 2026.9.7 → 2026.9.8-2
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/bin/clanker.mjs +258 -92
- package/lib/doctor.mjs +226 -0
- package/lib/foundry.mjs +114 -0
- package/lib/openclaw-wire.mjs +145 -0
- package/lib/operator-key.mjs +50 -0
- package/lib/profile.mjs +17 -9
- package/lib/resolve.mjs +57 -1
- package/lib/setup-detect.mjs +224 -0
- package/lib/setup.mjs +741 -0
- package/lib/ui.mjs +104 -0
- package/package.json +3 -1
package/bin/clanker.mjs
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
|
-
import { existsSync,
|
|
4
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
6
6
|
import os from "node:os";
|
|
7
7
|
import process from "node:process";
|
|
8
8
|
import { getAddress } from "viem";
|
|
9
9
|
import {
|
|
10
10
|
ANVIL_DEFAULT_PRIVATE_KEY,
|
|
11
|
-
harnessSnippet,
|
|
12
11
|
initProfile,
|
|
13
12
|
isLocalRpc,
|
|
14
13
|
loadConfig,
|
|
@@ -23,7 +22,21 @@ import {
|
|
|
23
22
|
readBot,
|
|
24
23
|
resolvePreferredOperator,
|
|
25
24
|
} from "../lib/identity-query.mjs";
|
|
26
|
-
import { resolveForRead, resolveOperatorKey } from "../lib/resolve.mjs";
|
|
25
|
+
import { resolveForRead, resolveOperatorKey, resolveReadIdentity } from "../lib/resolve.mjs";
|
|
26
|
+
import { runSetup } from "../lib/setup.mjs";
|
|
27
|
+
import { runDoctor } from "../lib/doctor.mjs";
|
|
28
|
+
import {
|
|
29
|
+
botIdentityCard,
|
|
30
|
+
botIdentityJson,
|
|
31
|
+
hubConnectChecklist,
|
|
32
|
+
wireOpenClawMqtt,
|
|
33
|
+
} from "../lib/openclaw-wire.mjs";
|
|
34
|
+
import {
|
|
35
|
+
c,
|
|
36
|
+
confirmPlan,
|
|
37
|
+
exitCliError,
|
|
38
|
+
nextHint,
|
|
39
|
+
} from "../lib/ui.mjs";
|
|
27
40
|
|
|
28
41
|
function resolveFoundryBinary(name) {
|
|
29
42
|
const home = os.homedir();
|
|
@@ -144,16 +157,18 @@ function usage() {
|
|
|
144
157
|
console.log(`clanker - clanker-chain helper CLI
|
|
145
158
|
|
|
146
159
|
Usage:
|
|
160
|
+
clanker setup [--preset sepolia|local] [--operator <label>] [--address 0x…] [--key-file path] [--force]
|
|
161
|
+
clanker doctor [--json]
|
|
147
162
|
clanker init --preset sepolia|local [--force]
|
|
148
|
-
clanker whoami [--json] [--operator <label>] [--address 0x…]
|
|
149
|
-
clanker operator mint <label> [--json]
|
|
150
|
-
clanker operator transfer propose <label> <newOwner>
|
|
151
|
-
clanker operator transfer accept <label>
|
|
152
|
-
clanker bot mint <label> [operator] [--json]
|
|
163
|
+
clanker whoami [--json] [--operator <label>] [--address 0x…] [--with-bots]
|
|
164
|
+
clanker operator mint <label> [--json] [--yes]
|
|
165
|
+
clanker operator transfer propose <label> <newOwner> [--yes]
|
|
166
|
+
clanker operator transfer accept <label> [--yes]
|
|
167
|
+
clanker bot mint <label> [operator] [--json] [--yes]
|
|
153
168
|
clanker bots [--json] [--operator <label>] [--address 0x…]
|
|
154
169
|
clanker bot status <label> [--json]
|
|
155
|
-
clanker bot revoke <label> [--json]
|
|
156
|
-
clanker bot rotate <label> <newKeyAddress> [--json]
|
|
170
|
+
clanker bot revoke <label> [--json] [--yes]
|
|
171
|
+
clanker bot rotate <label> <newKeyAddress> [--json] [--yes]
|
|
157
172
|
clanker init-openclaw
|
|
158
173
|
clanker chain up|deploy|mint-operator|mint-bot|rotate-bot-key|revoke-bot ...
|
|
159
174
|
clanker check mqtt <bot_id> <operator_id>
|
|
@@ -161,12 +176,12 @@ Usage:
|
|
|
161
176
|
|
|
162
177
|
Profile:
|
|
163
178
|
~/.clanker/config.json network preset (registry, RPC, broker URLs)
|
|
164
|
-
~/.clanker/operator.json label + owner + key pointer (never raw hex)
|
|
179
|
+
~/.clanker/operator.json label + owner + optional key pointer (never raw hex)
|
|
165
180
|
~/.clanker/keys/ bot keys (also written to ~/.openclaw/keys/)
|
|
166
181
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
182
|
+
Humans: \`clanker setup\` then \`clanker doctor\` / \`whoami\`.
|
|
183
|
+
Mutates print a plan and confirm unless --yes or --json.
|
|
184
|
+
whoami is fast by default; pass --with-bots to enrich child bots (or use \`clanker bots\`).
|
|
170
185
|
|
|
171
186
|
See docs/operator-cli.md.
|
|
172
187
|
`);
|
|
@@ -213,18 +228,20 @@ async function cmdWhoami(argv) {
|
|
|
213
228
|
let address;
|
|
214
229
|
let source;
|
|
215
230
|
let network;
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
network = resolveForRead(argv);
|
|
219
|
-
address = getAddress(addressFlag);
|
|
220
|
-
source = "--address";
|
|
221
|
-
} else {
|
|
222
|
-
const resolved = resolveOperatorKey(argv);
|
|
231
|
+
try {
|
|
232
|
+
const resolved = resolveReadIdentity(argv);
|
|
223
233
|
address = resolved.address;
|
|
224
234
|
source = resolved.source;
|
|
225
235
|
network = resolved.network;
|
|
236
|
+
} catch (err) {
|
|
237
|
+
exitCliError({
|
|
238
|
+
error: err.message,
|
|
239
|
+
because: "whoami needs an owner address from --address, a key, or operator.json",
|
|
240
|
+
try: ["clanker setup", "clanker doctor", "clanker whoami --address 0x…"],
|
|
241
|
+
});
|
|
226
242
|
}
|
|
227
243
|
|
|
244
|
+
const withBots = hasFlag(argv, "--with-bots");
|
|
228
245
|
const pub = await publicClientFromRpc(network.rpc);
|
|
229
246
|
const preferred =
|
|
230
247
|
flagValue(argv, "--operator") ?? loadOperator(network.home)?.label ?? null;
|
|
@@ -237,9 +254,14 @@ async function cmdWhoami(argv) {
|
|
|
237
254
|
owner: getAddress(address),
|
|
238
255
|
});
|
|
239
256
|
if (resolved.error) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
257
|
+
exitCliError({
|
|
258
|
+
error: resolved.error,
|
|
259
|
+
because: "preferred operator label did not match this owner on-chain",
|
|
260
|
+
try: [
|
|
261
|
+
"clanker whoami --address 0x…",
|
|
262
|
+
"clanker setup --force # fix label/owner",
|
|
263
|
+
],
|
|
264
|
+
});
|
|
243
265
|
}
|
|
244
266
|
selected = [resolved.operator];
|
|
245
267
|
} else {
|
|
@@ -250,12 +272,14 @@ async function cmdWhoami(argv) {
|
|
|
250
272
|
});
|
|
251
273
|
}
|
|
252
274
|
|
|
253
|
-
|
|
254
|
-
op
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
275
|
+
if (withBots) {
|
|
276
|
+
for (const op of selected) {
|
|
277
|
+
op.bots = await findBotsByOperator(pub, {
|
|
278
|
+
registry: network.registry,
|
|
279
|
+
operatorId: op.id,
|
|
280
|
+
fromBlock: network.fromBlock,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
259
283
|
}
|
|
260
284
|
|
|
261
285
|
const data = {
|
|
@@ -271,31 +295,38 @@ async function cmdWhoami(argv) {
|
|
|
271
295
|
active: o.active,
|
|
272
296
|
registeredAt: o.registeredAt.toString(),
|
|
273
297
|
revokedAt: o.revokedAt.toString(),
|
|
274
|
-
bots:
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
298
|
+
bots: withBots
|
|
299
|
+
? (o.bots ?? []).map((b) => ({
|
|
300
|
+
label: b.label,
|
|
301
|
+
botKey: b.botKey,
|
|
302
|
+
active: b.active,
|
|
303
|
+
registeredAt: b.registeredAt.toString(),
|
|
304
|
+
revokedAt: b.revokedAt.toString(),
|
|
305
|
+
}))
|
|
306
|
+
: [],
|
|
281
307
|
})),
|
|
282
308
|
};
|
|
283
309
|
|
|
284
310
|
if (hasFlag(argv, "--json")) printJson(data);
|
|
285
|
-
else
|
|
311
|
+
else {
|
|
312
|
+
printHumanWhoami(data);
|
|
313
|
+
if (!withBots && data.operators.length) {
|
|
314
|
+
console.log(c.dim("(bots omitted — pass --with-bots or run clanker bots)"));
|
|
315
|
+
}
|
|
316
|
+
nextHint(["clanker bots", "clanker doctor"]);
|
|
317
|
+
}
|
|
286
318
|
}
|
|
287
319
|
|
|
288
320
|
async function cmdBots(argv) {
|
|
289
321
|
let address;
|
|
290
322
|
let network;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
network = resolveForRead(argv);
|
|
294
|
-
address = getAddress(addressFlag);
|
|
295
|
-
} else {
|
|
296
|
-
const resolved = resolveOperatorKey(argv);
|
|
323
|
+
try {
|
|
324
|
+
const resolved = resolveReadIdentity(argv);
|
|
297
325
|
address = resolved.address;
|
|
298
326
|
network = resolved.network;
|
|
327
|
+
} catch (err) {
|
|
328
|
+
console.error(err.message);
|
|
329
|
+
process.exit(1);
|
|
299
330
|
}
|
|
300
331
|
const { label, pub } = await resolveOperatorLabel(argv, address, network);
|
|
301
332
|
const bots = await findBotsByOperator(pub, {
|
|
@@ -357,6 +388,27 @@ async function main() {
|
|
|
357
388
|
|
|
358
389
|
const repoRoot = findRepoRoot();
|
|
359
390
|
|
|
391
|
+
if (cmd === "setup") {
|
|
392
|
+
try {
|
|
393
|
+
await runSetup(rest);
|
|
394
|
+
} catch (err) {
|
|
395
|
+
exitCliError({
|
|
396
|
+
error: err.message,
|
|
397
|
+
because: "setup could not write a valid local profile",
|
|
398
|
+
try: [
|
|
399
|
+
"clanker setup --preset sepolia --operator org.you --address 0x… --yes --force",
|
|
400
|
+
"clanker doctor",
|
|
401
|
+
],
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (cmd === "doctor") {
|
|
408
|
+
const { exitCode } = await runDoctor(rest);
|
|
409
|
+
process.exit(exitCode);
|
|
410
|
+
}
|
|
411
|
+
|
|
360
412
|
if (cmd === "init") {
|
|
361
413
|
const preset = flagValue(rest, "--preset") ?? rest.find((a) => !a.startsWith("--"));
|
|
362
414
|
if (!preset || preset === "init") {
|
|
@@ -403,13 +455,38 @@ async function main() {
|
|
|
403
455
|
console.error("Usage: clanker operator mint <label>");
|
|
404
456
|
process.exit(1);
|
|
405
457
|
}
|
|
458
|
+
let planRows;
|
|
459
|
+
try {
|
|
460
|
+
const preview = resolveOperatorKey(flags);
|
|
461
|
+
planRows = [
|
|
462
|
+
["action", "registerOperator"],
|
|
463
|
+
["label", label],
|
|
464
|
+
["owner", preview.address],
|
|
465
|
+
["rpc", preview.network.rpc],
|
|
466
|
+
["registry", preview.network.registry ?? "(none)"],
|
|
467
|
+
["key", preview.source],
|
|
468
|
+
];
|
|
469
|
+
} catch (err) {
|
|
470
|
+
exitCliError({
|
|
471
|
+
error: err.message,
|
|
472
|
+
because: "operator mint needs a signing key on this network",
|
|
473
|
+
try: [
|
|
474
|
+
"export OPERATOR_PRIVATE_KEY=0x…",
|
|
475
|
+
"clanker operator mint " + label + " --key-file ~/.clanker/op.key --yes",
|
|
476
|
+
"clanker doctor",
|
|
477
|
+
],
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
const ok = await confirmPlan(flags, planRows, `Mint operator ${label}?`);
|
|
481
|
+
if (!ok) process.exit(0);
|
|
406
482
|
const result = await chainMintOperator(label, flags);
|
|
407
483
|
if (hasFlag(flags, "--json") || hasFlag(opArgv, "--json")) printJson(result);
|
|
408
484
|
else {
|
|
409
|
-
console.log(`Minted operator ${label}`);
|
|
485
|
+
console.log(c.green(`Minted operator ${label}`));
|
|
410
486
|
console.log(`owner: ${result.owner}`);
|
|
411
487
|
console.log(`tx: ${result.tx}`);
|
|
412
488
|
console.log(`Wrote ~/.clanker/operator.json`);
|
|
489
|
+
nextHint([`clanker bot mint <bot_label>`, "clanker whoami"]);
|
|
413
490
|
}
|
|
414
491
|
return;
|
|
415
492
|
}
|
|
@@ -421,9 +498,23 @@ async function main() {
|
|
|
421
498
|
console.error("Usage: clanker operator transfer propose <label> <newOwner>");
|
|
422
499
|
process.exit(1);
|
|
423
500
|
}
|
|
501
|
+
const ok = await confirmPlan(
|
|
502
|
+
flags,
|
|
503
|
+
[
|
|
504
|
+
["action", "proposeOperatorTransfer"],
|
|
505
|
+
["label", label],
|
|
506
|
+
["newOwner", getAddress(newOwner)],
|
|
507
|
+
],
|
|
508
|
+
`Propose transfer of ${label}?`,
|
|
509
|
+
);
|
|
510
|
+
if (!ok) process.exit(0);
|
|
424
511
|
const result = await chainProposeOperatorTransfer(label, getAddress(newOwner), flags);
|
|
425
512
|
if (hasFlag(flags, "--json")) printJson(result);
|
|
426
|
-
else
|
|
513
|
+
else {
|
|
514
|
+
console.log(c.green(`Proposed transfer of ${label} → ${newOwner}`));
|
|
515
|
+
console.log(`tx: ${result.tx}`);
|
|
516
|
+
nextHint([`clanker operator transfer accept ${label} # as new owner`]);
|
|
517
|
+
}
|
|
427
518
|
return;
|
|
428
519
|
}
|
|
429
520
|
if (action === "accept") {
|
|
@@ -431,9 +522,23 @@ async function main() {
|
|
|
431
522
|
console.error("Usage: clanker operator transfer accept <label>");
|
|
432
523
|
process.exit(1);
|
|
433
524
|
}
|
|
525
|
+
const ok = await confirmPlan(
|
|
526
|
+
flags,
|
|
527
|
+
[
|
|
528
|
+
["action", "acceptOperatorTransfer"],
|
|
529
|
+
["label", label],
|
|
530
|
+
],
|
|
531
|
+
`Accept transfer of ${label}?`,
|
|
532
|
+
);
|
|
533
|
+
if (!ok) process.exit(0);
|
|
434
534
|
const result = await chainAcceptOperatorTransfer(label, flags);
|
|
435
535
|
if (hasFlag(flags, "--json")) printJson(result);
|
|
436
|
-
else
|
|
536
|
+
else {
|
|
537
|
+
console.log(c.green(`Accepted transfer of ${label}`));
|
|
538
|
+
console.log(`owner: ${result.owner}`);
|
|
539
|
+
console.log(`tx: ${result.tx}`);
|
|
540
|
+
nextHint(["clanker whoami", "clanker bots"]);
|
|
541
|
+
}
|
|
437
542
|
return;
|
|
438
543
|
}
|
|
439
544
|
console.error("Usage: clanker operator transfer propose|accept ...");
|
|
@@ -473,20 +578,76 @@ async function main() {
|
|
|
473
578
|
}
|
|
474
579
|
let operatorLabel = operatorArg ?? flagValue(flags, "--operator") ?? null;
|
|
475
580
|
if (!operatorLabel) {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
581
|
+
try {
|
|
582
|
+
const { address, network } = resolveOperatorKey(flags);
|
|
583
|
+
const inferred = await resolveOperatorLabel(flags, address, network);
|
|
584
|
+
operatorLabel = inferred.label;
|
|
585
|
+
} catch (err) {
|
|
586
|
+
exitCliError({
|
|
587
|
+
error: err.message,
|
|
588
|
+
because: "bot mint needs an operator label or a resolvable signing key",
|
|
589
|
+
try: [
|
|
590
|
+
`clanker bot mint ${botLabel} <operator_label> --yes`,
|
|
591
|
+
"clanker setup",
|
|
592
|
+
],
|
|
593
|
+
});
|
|
594
|
+
}
|
|
479
595
|
}
|
|
596
|
+
const ok = await confirmPlan(
|
|
597
|
+
flags,
|
|
598
|
+
[
|
|
599
|
+
["action", "registerBot"],
|
|
600
|
+
["bot", botLabel],
|
|
601
|
+
["operator", operatorLabel],
|
|
602
|
+
],
|
|
603
|
+
`Mint bot ${botLabel} under ${operatorLabel}?`,
|
|
604
|
+
);
|
|
605
|
+
if (!ok) process.exit(0);
|
|
480
606
|
const result = await chainMintBot(botLabel, operatorLabel, flags);
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
607
|
+
const mqtt = result.channels_mqtt ?? {};
|
|
608
|
+
const wire = wireOpenClawMqtt({
|
|
609
|
+
botId: botLabel,
|
|
610
|
+
operatorId: operatorLabel,
|
|
611
|
+
network: {
|
|
612
|
+
rpc: mqtt.chainRpcUrl,
|
|
613
|
+
registry: mqtt.registryAddress,
|
|
614
|
+
brokerUrl: mqtt.brokerUrl,
|
|
615
|
+
mqttAuthServiceUrl: mqtt.mqttAuthServiceUrl,
|
|
616
|
+
},
|
|
617
|
+
keyPath: result.key_path,
|
|
618
|
+
});
|
|
619
|
+
if (hasFlag(flags, "--json")) {
|
|
620
|
+
printJson({
|
|
621
|
+
...result,
|
|
622
|
+
openclaw: wire,
|
|
623
|
+
bot_identity: botIdentityJson({
|
|
624
|
+
botId: botLabel,
|
|
625
|
+
keyPath: result.key_path,
|
|
626
|
+
openclawConfigPath: wire.path,
|
|
627
|
+
}),
|
|
628
|
+
});
|
|
629
|
+
} else {
|
|
630
|
+
console.log(c.green(`Minted bot ${botLabel} under ${operatorLabel}`));
|
|
484
631
|
console.log(`botKey: ${result.bot_key}`);
|
|
485
|
-
console.log(`key file: ${result.key_path}`);
|
|
486
|
-
console.log(`also: ${result.clanker_key_path}`);
|
|
487
632
|
console.log(`tx: ${result.tx}`);
|
|
488
|
-
console.log(
|
|
489
|
-
console.log(
|
|
633
|
+
console.log(c.dim(`also: ${result.clanker_key_path}`));
|
|
634
|
+
console.log("");
|
|
635
|
+
for (const line of botIdentityCard({
|
|
636
|
+
botId: botLabel,
|
|
637
|
+
operatorId: operatorLabel,
|
|
638
|
+
keyPath: result.key_path,
|
|
639
|
+
openclawPath: wire.path,
|
|
640
|
+
created: wire.created,
|
|
641
|
+
})) {
|
|
642
|
+
console.log(line);
|
|
643
|
+
}
|
|
644
|
+
nextHint(
|
|
645
|
+
hubConnectChecklist({
|
|
646
|
+
botId: botLabel,
|
|
647
|
+
channelsMqtt: wire.channelsMqtt,
|
|
648
|
+
pluginPin: wire.pluginPin,
|
|
649
|
+
}),
|
|
650
|
+
);
|
|
490
651
|
}
|
|
491
652
|
return;
|
|
492
653
|
}
|
|
@@ -497,9 +658,22 @@ async function main() {
|
|
|
497
658
|
console.error("Usage: clanker bot revoke <label>");
|
|
498
659
|
process.exit(1);
|
|
499
660
|
}
|
|
661
|
+
const ok = await confirmPlan(
|
|
662
|
+
flags,
|
|
663
|
+
[
|
|
664
|
+
["action", "revokeBot"],
|
|
665
|
+
["bot", botLabel],
|
|
666
|
+
],
|
|
667
|
+
`Revoke bot ${botLabel}?`,
|
|
668
|
+
);
|
|
669
|
+
if (!ok) process.exit(0);
|
|
500
670
|
const result = await chainRevokeBot(botLabel, flags);
|
|
501
671
|
if (hasFlag(flags, "--json")) printJson(result);
|
|
502
|
-
else
|
|
672
|
+
else {
|
|
673
|
+
console.log(c.yellow(`Revoked ${botLabel}`));
|
|
674
|
+
console.log(`tx: ${result.tx}`);
|
|
675
|
+
nextHint(["clanker bots", "clanker bot status " + botLabel]);
|
|
676
|
+
}
|
|
503
677
|
return;
|
|
504
678
|
}
|
|
505
679
|
|
|
@@ -509,9 +683,23 @@ async function main() {
|
|
|
509
683
|
console.error("Usage: clanker bot rotate <label> <newKeyAddress>");
|
|
510
684
|
process.exit(1);
|
|
511
685
|
}
|
|
686
|
+
const ok = await confirmPlan(
|
|
687
|
+
flags,
|
|
688
|
+
[
|
|
689
|
+
["action", "rotateBotKey"],
|
|
690
|
+
["bot", botLabel],
|
|
691
|
+
["newKey", getAddress(newKey)],
|
|
692
|
+
],
|
|
693
|
+
`Rotate key for ${botLabel}?`,
|
|
694
|
+
);
|
|
695
|
+
if (!ok) process.exit(0);
|
|
512
696
|
const result = await chainRotateBotKey(botLabel, getAddress(newKey), flags);
|
|
513
697
|
if (hasFlag(flags, "--json")) printJson(result);
|
|
514
|
-
else
|
|
698
|
+
else {
|
|
699
|
+
console.log(c.green(`Rotated ${botLabel} → ${newKey}`));
|
|
700
|
+
console.log(`tx: ${result.tx}`);
|
|
701
|
+
nextHint(["Update ~/.openclaw/keys/" + botLabel + ".key", "clanker bot status " + botLabel]);
|
|
702
|
+
}
|
|
515
703
|
return;
|
|
516
704
|
}
|
|
517
705
|
|
|
@@ -717,22 +905,6 @@ async function main() {
|
|
|
717
905
|
}
|
|
718
906
|
|
|
719
907
|
if (cmd === "init-openclaw") {
|
|
720
|
-
const home = os.homedir();
|
|
721
|
-
const openclawDir = join(home, ".openclaw");
|
|
722
|
-
const cfgPath = join(openclawDir, "openclaw.json");
|
|
723
|
-
if (!existsSync(openclawDir)) {
|
|
724
|
-
mkdirSync(openclawDir, { recursive: true });
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
if (existsSync(cfgPath)) {
|
|
728
|
-
console.log(`${cfgPath} already exists.`);
|
|
729
|
-
console.log(
|
|
730
|
-
'Ensure plugins.enabled includes "mqtt" and "mqtt-tools", and channels.mqtt has botId, operatorId, brokerUrl, chainRpcUrl, registryAddress.',
|
|
731
|
-
);
|
|
732
|
-
console.log("See SETUP.md and docs/operator-cli.md.");
|
|
733
|
-
process.exit(0);
|
|
734
|
-
}
|
|
735
|
-
|
|
736
908
|
const profile = loadConfig();
|
|
737
909
|
const operator = loadOperator();
|
|
738
910
|
// No profile: local defaults only — do not mix Sepolia registry with localhost MQTT.
|
|
@@ -750,27 +922,21 @@ async function main() {
|
|
|
750
922
|
mqttAuthServiceUrl: "http://localhost:9090",
|
|
751
923
|
};
|
|
752
924
|
|
|
753
|
-
const
|
|
925
|
+
const wire = wireOpenClawMqtt({
|
|
754
926
|
botId: "openclaw.your-bot.local",
|
|
755
927
|
operatorId: operator?.label ?? "org.openclaw.your-operator",
|
|
756
928
|
network,
|
|
757
929
|
});
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
},
|
|
769
|
-
};
|
|
770
|
-
writeFileSync(cfgPath, JSON.stringify(cfg, null, 2), "utf8");
|
|
771
|
-
console.log(`Created ${cfgPath} with mqtt + mqtt-tools from ${profile ? "active" : "default"} preset.`);
|
|
772
|
-
console.log("Next: clanker bot mint <label>, then set channels.mqtt.botId / operatorId.");
|
|
773
|
-
console.log("See docs/operator-cli.md and SETUP.md.");
|
|
930
|
+
console.log(
|
|
931
|
+
wire.created
|
|
932
|
+
? `Created ${wire.path} with mqtt + mqtt-tools from ${profile ? "active" : "default"} preset.`
|
|
933
|
+
: `Updated channels.mqtt in ${wire.path} (plugins mqtt + mqtt-tools ensured).`,
|
|
934
|
+
);
|
|
935
|
+
nextHint([
|
|
936
|
+
"clanker bot mint <label>",
|
|
937
|
+
"Then channels.mqtt.botId / operatorId / privateKeyFile update automatically",
|
|
938
|
+
"See docs/operator-cli.md and docs/closed-beta-invite.md",
|
|
939
|
+
]);
|
|
774
940
|
process.exit(0);
|
|
775
941
|
}
|
|
776
942
|
|