@clanker-chain/clanker-cli 2026.9.7-4 → 2026.9.7
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 +51 -203
- package/lib/profile.mjs +9 -17
- package/lib/resolve.mjs +1 -57
- package/package.json +1 -3
- package/lib/doctor.mjs +0 -185
- package/lib/setup-detect.mjs +0 -224
- package/lib/setup.mjs +0 -549
- package/lib/ui.mjs +0 -104
package/bin/clanker.mjs
CHANGED
|
@@ -23,15 +23,7 @@ import {
|
|
|
23
23
|
readBot,
|
|
24
24
|
resolvePreferredOperator,
|
|
25
25
|
} from "../lib/identity-query.mjs";
|
|
26
|
-
import { resolveForRead, resolveOperatorKey
|
|
27
|
-
import { runSetup } from "../lib/setup.mjs";
|
|
28
|
-
import { runDoctor } from "../lib/doctor.mjs";
|
|
29
|
-
import {
|
|
30
|
-
c,
|
|
31
|
-
confirmPlan,
|
|
32
|
-
exitCliError,
|
|
33
|
-
nextHint,
|
|
34
|
-
} from "../lib/ui.mjs";
|
|
26
|
+
import { resolveForRead, resolveOperatorKey } from "../lib/resolve.mjs";
|
|
35
27
|
|
|
36
28
|
function resolveFoundryBinary(name) {
|
|
37
29
|
const home = os.homedir();
|
|
@@ -152,18 +144,16 @@ function usage() {
|
|
|
152
144
|
console.log(`clanker - clanker-chain helper CLI
|
|
153
145
|
|
|
154
146
|
Usage:
|
|
155
|
-
clanker setup [--preset sepolia|local] [--operator <label>] [--address 0x…] [--key-file path] [--force]
|
|
156
|
-
clanker doctor [--json]
|
|
157
147
|
clanker init --preset sepolia|local [--force]
|
|
158
|
-
clanker whoami [--json] [--operator <label>] [--address 0x…]
|
|
159
|
-
clanker operator mint <label> [--json]
|
|
160
|
-
clanker operator transfer propose <label> <newOwner>
|
|
161
|
-
clanker operator transfer accept <label>
|
|
162
|
-
clanker bot mint <label> [operator] [--json]
|
|
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
153
|
clanker bots [--json] [--operator <label>] [--address 0x…]
|
|
164
154
|
clanker bot status <label> [--json]
|
|
165
|
-
clanker bot revoke <label> [--json]
|
|
166
|
-
clanker bot rotate <label> <newKeyAddress> [--json]
|
|
155
|
+
clanker bot revoke <label> [--json]
|
|
156
|
+
clanker bot rotate <label> <newKeyAddress> [--json]
|
|
167
157
|
clanker init-openclaw
|
|
168
158
|
clanker chain up|deploy|mint-operator|mint-bot|rotate-bot-key|revoke-bot ...
|
|
169
159
|
clanker check mqtt <bot_id> <operator_id>
|
|
@@ -171,12 +161,12 @@ Usage:
|
|
|
171
161
|
|
|
172
162
|
Profile:
|
|
173
163
|
~/.clanker/config.json network preset (registry, RPC, broker URLs)
|
|
174
|
-
~/.clanker/operator.json label + owner +
|
|
164
|
+
~/.clanker/operator.json label + owner + key pointer (never raw hex)
|
|
175
165
|
~/.clanker/keys/ bot keys (also written to ~/.openclaw/keys/)
|
|
176
166
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
167
|
+
Key resolution (mutating commands):
|
|
168
|
+
--key > --key-file > OPERATOR_PRIVATE_KEY > profile keyFile > profile env
|
|
169
|
+
Anvil account #0 is allowed only on localhost RPC.
|
|
180
170
|
|
|
181
171
|
See docs/operator-cli.md.
|
|
182
172
|
`);
|
|
@@ -223,20 +213,18 @@ async function cmdWhoami(argv) {
|
|
|
223
213
|
let address;
|
|
224
214
|
let source;
|
|
225
215
|
let network;
|
|
226
|
-
|
|
227
|
-
|
|
216
|
+
const addressFlag = flagValue(argv, "--address");
|
|
217
|
+
if (addressFlag) {
|
|
218
|
+
network = resolveForRead(argv);
|
|
219
|
+
address = getAddress(addressFlag);
|
|
220
|
+
source = "--address";
|
|
221
|
+
} else {
|
|
222
|
+
const resolved = resolveOperatorKey(argv);
|
|
228
223
|
address = resolved.address;
|
|
229
224
|
source = resolved.source;
|
|
230
225
|
network = resolved.network;
|
|
231
|
-
} catch (err) {
|
|
232
|
-
exitCliError({
|
|
233
|
-
error: err.message,
|
|
234
|
-
because: "whoami needs an owner address from --address, a key, or operator.json",
|
|
235
|
-
try: ["clanker setup", "clanker doctor", "clanker whoami --address 0x…"],
|
|
236
|
-
});
|
|
237
226
|
}
|
|
238
227
|
|
|
239
|
-
const withBots = hasFlag(argv, "--with-bots");
|
|
240
228
|
const pub = await publicClientFromRpc(network.rpc);
|
|
241
229
|
const preferred =
|
|
242
230
|
flagValue(argv, "--operator") ?? loadOperator(network.home)?.label ?? null;
|
|
@@ -249,14 +237,9 @@ async function cmdWhoami(argv) {
|
|
|
249
237
|
owner: getAddress(address),
|
|
250
238
|
});
|
|
251
239
|
if (resolved.error) {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
try: [
|
|
256
|
-
"clanker whoami --address 0x…",
|
|
257
|
-
"clanker setup --force # fix label/owner",
|
|
258
|
-
],
|
|
259
|
-
});
|
|
240
|
+
const err = new Error(resolved.error);
|
|
241
|
+
err.candidates = resolved.candidates;
|
|
242
|
+
throw err;
|
|
260
243
|
}
|
|
261
244
|
selected = [resolved.operator];
|
|
262
245
|
} else {
|
|
@@ -267,14 +250,12 @@ async function cmdWhoami(argv) {
|
|
|
267
250
|
});
|
|
268
251
|
}
|
|
269
252
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
});
|
|
277
|
-
}
|
|
253
|
+
for (const op of selected) {
|
|
254
|
+
op.bots = await findBotsByOperator(pub, {
|
|
255
|
+
registry: network.registry,
|
|
256
|
+
operatorId: op.id,
|
|
257
|
+
fromBlock: network.fromBlock,
|
|
258
|
+
});
|
|
278
259
|
}
|
|
279
260
|
|
|
280
261
|
const data = {
|
|
@@ -290,38 +271,31 @@ async function cmdWhoami(argv) {
|
|
|
290
271
|
active: o.active,
|
|
291
272
|
registeredAt: o.registeredAt.toString(),
|
|
292
273
|
revokedAt: o.revokedAt.toString(),
|
|
293
|
-
bots:
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
}))
|
|
301
|
-
: [],
|
|
274
|
+
bots: (o.bots ?? []).map((b) => ({
|
|
275
|
+
label: b.label,
|
|
276
|
+
botKey: b.botKey,
|
|
277
|
+
active: b.active,
|
|
278
|
+
registeredAt: b.registeredAt.toString(),
|
|
279
|
+
revokedAt: b.revokedAt.toString(),
|
|
280
|
+
})),
|
|
302
281
|
})),
|
|
303
282
|
};
|
|
304
283
|
|
|
305
284
|
if (hasFlag(argv, "--json")) printJson(data);
|
|
306
|
-
else
|
|
307
|
-
printHumanWhoami(data);
|
|
308
|
-
if (!withBots && data.operators.length) {
|
|
309
|
-
console.log(c.dim("(bots omitted — pass --with-bots or run clanker bots)"));
|
|
310
|
-
}
|
|
311
|
-
nextHint(["clanker bots", "clanker doctor"]);
|
|
312
|
-
}
|
|
285
|
+
else printHumanWhoami(data);
|
|
313
286
|
}
|
|
314
287
|
|
|
315
288
|
async function cmdBots(argv) {
|
|
316
289
|
let address;
|
|
317
290
|
let network;
|
|
318
|
-
|
|
319
|
-
|
|
291
|
+
const addressFlag = flagValue(argv, "--address");
|
|
292
|
+
if (addressFlag) {
|
|
293
|
+
network = resolveForRead(argv);
|
|
294
|
+
address = getAddress(addressFlag);
|
|
295
|
+
} else {
|
|
296
|
+
const resolved = resolveOperatorKey(argv);
|
|
320
297
|
address = resolved.address;
|
|
321
298
|
network = resolved.network;
|
|
322
|
-
} catch (err) {
|
|
323
|
-
console.error(err.message);
|
|
324
|
-
process.exit(1);
|
|
325
299
|
}
|
|
326
300
|
const { label, pub } = await resolveOperatorLabel(argv, address, network);
|
|
327
301
|
const bots = await findBotsByOperator(pub, {
|
|
@@ -383,27 +357,6 @@ async function main() {
|
|
|
383
357
|
|
|
384
358
|
const repoRoot = findRepoRoot();
|
|
385
359
|
|
|
386
|
-
if (cmd === "setup") {
|
|
387
|
-
try {
|
|
388
|
-
await runSetup(rest);
|
|
389
|
-
} catch (err) {
|
|
390
|
-
exitCliError({
|
|
391
|
-
error: err.message,
|
|
392
|
-
because: "setup could not write a valid local profile",
|
|
393
|
-
try: [
|
|
394
|
-
"clanker setup --preset sepolia --operator org.you --address 0x… --yes --force",
|
|
395
|
-
"clanker doctor",
|
|
396
|
-
],
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
if (cmd === "doctor") {
|
|
403
|
-
const { exitCode } = await runDoctor(rest);
|
|
404
|
-
process.exit(exitCode);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
360
|
if (cmd === "init") {
|
|
408
361
|
const preset = flagValue(rest, "--preset") ?? rest.find((a) => !a.startsWith("--"));
|
|
409
362
|
if (!preset || preset === "init") {
|
|
@@ -450,38 +403,13 @@ async function main() {
|
|
|
450
403
|
console.error("Usage: clanker operator mint <label>");
|
|
451
404
|
process.exit(1);
|
|
452
405
|
}
|
|
453
|
-
let planRows;
|
|
454
|
-
try {
|
|
455
|
-
const preview = resolveOperatorKey(flags);
|
|
456
|
-
planRows = [
|
|
457
|
-
["action", "registerOperator"],
|
|
458
|
-
["label", label],
|
|
459
|
-
["owner", preview.address],
|
|
460
|
-
["rpc", preview.network.rpc],
|
|
461
|
-
["registry", preview.network.registry ?? "(none)"],
|
|
462
|
-
["key", preview.source],
|
|
463
|
-
];
|
|
464
|
-
} catch (err) {
|
|
465
|
-
exitCliError({
|
|
466
|
-
error: err.message,
|
|
467
|
-
because: "operator mint needs a signing key on this network",
|
|
468
|
-
try: [
|
|
469
|
-
"export OPERATOR_PRIVATE_KEY=0x…",
|
|
470
|
-
"clanker operator mint " + label + " --key-file ~/.clanker/op.key --yes",
|
|
471
|
-
"clanker doctor",
|
|
472
|
-
],
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
const ok = await confirmPlan(flags, planRows, `Mint operator ${label}?`);
|
|
476
|
-
if (!ok) process.exit(0);
|
|
477
406
|
const result = await chainMintOperator(label, flags);
|
|
478
407
|
if (hasFlag(flags, "--json") || hasFlag(opArgv, "--json")) printJson(result);
|
|
479
408
|
else {
|
|
480
|
-
console.log(
|
|
409
|
+
console.log(`Minted operator ${label}`);
|
|
481
410
|
console.log(`owner: ${result.owner}`);
|
|
482
411
|
console.log(`tx: ${result.tx}`);
|
|
483
412
|
console.log(`Wrote ~/.clanker/operator.json`);
|
|
484
|
-
nextHint([`clanker bot mint <bot_label>`, "clanker whoami"]);
|
|
485
413
|
}
|
|
486
414
|
return;
|
|
487
415
|
}
|
|
@@ -493,23 +421,9 @@ async function main() {
|
|
|
493
421
|
console.error("Usage: clanker operator transfer propose <label> <newOwner>");
|
|
494
422
|
process.exit(1);
|
|
495
423
|
}
|
|
496
|
-
const ok = await confirmPlan(
|
|
497
|
-
flags,
|
|
498
|
-
[
|
|
499
|
-
["action", "proposeOperatorTransfer"],
|
|
500
|
-
["label", label],
|
|
501
|
-
["newOwner", getAddress(newOwner)],
|
|
502
|
-
],
|
|
503
|
-
`Propose transfer of ${label}?`,
|
|
504
|
-
);
|
|
505
|
-
if (!ok) process.exit(0);
|
|
506
424
|
const result = await chainProposeOperatorTransfer(label, getAddress(newOwner), flags);
|
|
507
425
|
if (hasFlag(flags, "--json")) printJson(result);
|
|
508
|
-
else {
|
|
509
|
-
console.log(c.green(`Proposed transfer of ${label} → ${newOwner}`));
|
|
510
|
-
console.log(`tx: ${result.tx}`);
|
|
511
|
-
nextHint([`clanker operator transfer accept ${label} # as new owner`]);
|
|
512
|
-
}
|
|
426
|
+
else console.log(`Proposed transfer of ${label} → ${newOwner}\ntx: ${result.tx}`);
|
|
513
427
|
return;
|
|
514
428
|
}
|
|
515
429
|
if (action === "accept") {
|
|
@@ -517,23 +431,9 @@ async function main() {
|
|
|
517
431
|
console.error("Usage: clanker operator transfer accept <label>");
|
|
518
432
|
process.exit(1);
|
|
519
433
|
}
|
|
520
|
-
const ok = await confirmPlan(
|
|
521
|
-
flags,
|
|
522
|
-
[
|
|
523
|
-
["action", "acceptOperatorTransfer"],
|
|
524
|
-
["label", label],
|
|
525
|
-
],
|
|
526
|
-
`Accept transfer of ${label}?`,
|
|
527
|
-
);
|
|
528
|
-
if (!ok) process.exit(0);
|
|
529
434
|
const result = await chainAcceptOperatorTransfer(label, flags);
|
|
530
435
|
if (hasFlag(flags, "--json")) printJson(result);
|
|
531
|
-
else {
|
|
532
|
-
console.log(c.green(`Accepted transfer of ${label}`));
|
|
533
|
-
console.log(`owner: ${result.owner}`);
|
|
534
|
-
console.log(`tx: ${result.tx}`);
|
|
535
|
-
nextHint(["clanker whoami", "clanker bots"]);
|
|
536
|
-
}
|
|
436
|
+
else console.log(`Accepted transfer of ${label}\nowner: ${result.owner}\ntx: ${result.tx}`);
|
|
537
437
|
return;
|
|
538
438
|
}
|
|
539
439
|
console.error("Usage: clanker operator transfer propose|accept ...");
|
|
@@ -573,45 +473,20 @@ async function main() {
|
|
|
573
473
|
}
|
|
574
474
|
let operatorLabel = operatorArg ?? flagValue(flags, "--operator") ?? null;
|
|
575
475
|
if (!operatorLabel) {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
operatorLabel = inferred.label;
|
|
580
|
-
} catch (err) {
|
|
581
|
-
exitCliError({
|
|
582
|
-
error: err.message,
|
|
583
|
-
because: "bot mint needs an operator label or a resolvable signing key",
|
|
584
|
-
try: [
|
|
585
|
-
`clanker bot mint ${botLabel} <operator_label> --yes`,
|
|
586
|
-
"clanker setup",
|
|
587
|
-
],
|
|
588
|
-
});
|
|
589
|
-
}
|
|
476
|
+
const { address, network } = resolveOperatorKey(flags);
|
|
477
|
+
const inferred = await resolveOperatorLabel(flags, address, network);
|
|
478
|
+
operatorLabel = inferred.label;
|
|
590
479
|
}
|
|
591
|
-
const ok = await confirmPlan(
|
|
592
|
-
flags,
|
|
593
|
-
[
|
|
594
|
-
["action", "registerBot"],
|
|
595
|
-
["bot", botLabel],
|
|
596
|
-
["operator", operatorLabel],
|
|
597
|
-
],
|
|
598
|
-
`Mint bot ${botLabel} under ${operatorLabel}?`,
|
|
599
|
-
);
|
|
600
|
-
if (!ok) process.exit(0);
|
|
601
480
|
const result = await chainMintBot(botLabel, operatorLabel, flags);
|
|
602
481
|
if (hasFlag(flags, "--json")) printJson(result);
|
|
603
482
|
else {
|
|
604
|
-
console.log(
|
|
483
|
+
console.log(`Minted bot ${botLabel} under ${operatorLabel}`);
|
|
605
484
|
console.log(`botKey: ${result.bot_key}`);
|
|
606
485
|
console.log(`key file: ${result.key_path}`);
|
|
607
486
|
console.log(`also: ${result.clanker_key_path}`);
|
|
608
487
|
console.log(`tx: ${result.tx}`);
|
|
609
488
|
console.log("\nchannels.mqtt stub:");
|
|
610
489
|
console.log(JSON.stringify(result.channels_mqtt, null, 2));
|
|
611
|
-
nextHint([
|
|
612
|
-
"Paste channels.mqtt into openclaw.json",
|
|
613
|
-
"openclaw plugins install @clanker-chain/mqtt-channel-plugin@…",
|
|
614
|
-
]);
|
|
615
490
|
}
|
|
616
491
|
return;
|
|
617
492
|
}
|
|
@@ -622,22 +497,9 @@ async function main() {
|
|
|
622
497
|
console.error("Usage: clanker bot revoke <label>");
|
|
623
498
|
process.exit(1);
|
|
624
499
|
}
|
|
625
|
-
const ok = await confirmPlan(
|
|
626
|
-
flags,
|
|
627
|
-
[
|
|
628
|
-
["action", "revokeBot"],
|
|
629
|
-
["bot", botLabel],
|
|
630
|
-
],
|
|
631
|
-
`Revoke bot ${botLabel}?`,
|
|
632
|
-
);
|
|
633
|
-
if (!ok) process.exit(0);
|
|
634
500
|
const result = await chainRevokeBot(botLabel, flags);
|
|
635
501
|
if (hasFlag(flags, "--json")) printJson(result);
|
|
636
|
-
else {
|
|
637
|
-
console.log(c.yellow(`Revoked ${botLabel}`));
|
|
638
|
-
console.log(`tx: ${result.tx}`);
|
|
639
|
-
nextHint(["clanker bots", "clanker bot status " + botLabel]);
|
|
640
|
-
}
|
|
502
|
+
else console.log(`Revoked ${botLabel}\ntx: ${result.tx}`);
|
|
641
503
|
return;
|
|
642
504
|
}
|
|
643
505
|
|
|
@@ -647,23 +509,9 @@ async function main() {
|
|
|
647
509
|
console.error("Usage: clanker bot rotate <label> <newKeyAddress>");
|
|
648
510
|
process.exit(1);
|
|
649
511
|
}
|
|
650
|
-
const ok = await confirmPlan(
|
|
651
|
-
flags,
|
|
652
|
-
[
|
|
653
|
-
["action", "rotateBotKey"],
|
|
654
|
-
["bot", botLabel],
|
|
655
|
-
["newKey", getAddress(newKey)],
|
|
656
|
-
],
|
|
657
|
-
`Rotate key for ${botLabel}?`,
|
|
658
|
-
);
|
|
659
|
-
if (!ok) process.exit(0);
|
|
660
512
|
const result = await chainRotateBotKey(botLabel, getAddress(newKey), flags);
|
|
661
513
|
if (hasFlag(flags, "--json")) printJson(result);
|
|
662
|
-
else {
|
|
663
|
-
console.log(c.green(`Rotated ${botLabel} → ${newKey}`));
|
|
664
|
-
console.log(`tx: ${result.tx}`);
|
|
665
|
-
nextHint(["Update ~/.openclaw/keys/" + botLabel + ".key", "clanker bot status " + botLabel]);
|
|
666
|
-
}
|
|
514
|
+
else console.log(`Rotated ${botLabel} → ${newKey}\ntx: ${result.tx}`);
|
|
667
515
|
return;
|
|
668
516
|
}
|
|
669
517
|
|
package/lib/profile.mjs
CHANGED
|
@@ -17,14 +17,11 @@ export const ANVIL_DEFAULT_ADDRESS = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
|
|
|
17
17
|
export const SEPOLIA_REGISTRY = "0xD650467f9D7A20f37E55ec23Ca1c711598f97958";
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Safe floor for Sepolia getLogs (before registry deploy).
|
|
21
|
-
*
|
|
20
|
+
* Safe floor for Sepolia getLogs (before registry deploy). Documented so scans
|
|
21
|
+
* stay cheap; bump only if you redeploy the registry earlier.
|
|
22
22
|
*/
|
|
23
23
|
export const SEPOLIA_FROM_BLOCK = 35_000_000n;
|
|
24
24
|
|
|
25
|
-
/** Default Sepolia fromBlock for public RPC (faster whoami/bots scans). */
|
|
26
|
-
export const SEPOLIA_FAST_FROM_BLOCK = 46_000_000n;
|
|
27
|
-
|
|
28
25
|
export const PRESETS = {
|
|
29
26
|
local: {
|
|
30
27
|
preset: "local",
|
|
@@ -40,7 +37,7 @@ export const PRESETS = {
|
|
|
40
37
|
chainRpcUrl: "https://sepolia.base.org",
|
|
41
38
|
brokerUrl: "mqtts://mqtt.clanker-chain.com:8883",
|
|
42
39
|
mqttAuthServiceUrl: "https://mqtt-auth.clanker-chain.com",
|
|
43
|
-
fromBlock:
|
|
40
|
+
fromBlock: SEPOLIA_FROM_BLOCK,
|
|
44
41
|
},
|
|
45
42
|
};
|
|
46
43
|
|
|
@@ -66,7 +63,7 @@ export function openclawKeysDir() {
|
|
|
66
63
|
|
|
67
64
|
/**
|
|
68
65
|
* @param {string} presetName
|
|
69
|
-
* @param {{ force?: boolean, registryAddress?: string|null, home?: string
|
|
66
|
+
* @param {{ force?: boolean, registryAddress?: string|null, home?: string }} [opts]
|
|
70
67
|
*/
|
|
71
68
|
export function initProfile(presetName, opts = {}) {
|
|
72
69
|
const name = String(presetName || "").toLowerCase();
|
|
@@ -82,15 +79,13 @@ export function initProfile(presetName, opts = {}) {
|
|
|
82
79
|
}
|
|
83
80
|
mkdirSync(home, { recursive: true });
|
|
84
81
|
const preset = PRESETS[name];
|
|
85
|
-
const fromBlock =
|
|
86
|
-
opts.fromBlock != null ? BigInt(opts.fromBlock) : preset.fromBlock;
|
|
87
82
|
const config = {
|
|
88
83
|
preset: preset.preset,
|
|
89
84
|
registryAddress: opts.registryAddress ?? preset.registryAddress,
|
|
90
85
|
chainRpcUrl: preset.chainRpcUrl,
|
|
91
86
|
brokerUrl: preset.brokerUrl,
|
|
92
87
|
mqttAuthServiceUrl: preset.mqttAuthServiceUrl,
|
|
93
|
-
fromBlock: fromBlock.toString(),
|
|
88
|
+
fromBlock: preset.fromBlock.toString(),
|
|
94
89
|
};
|
|
95
90
|
if (name === "local" && !config.registryAddress) {
|
|
96
91
|
// Placeholder until chain deploy; operator must set after forge deploy.
|
|
@@ -125,9 +120,8 @@ export function loadOperator(home = clankerHome()) {
|
|
|
125
120
|
}
|
|
126
121
|
|
|
127
122
|
/**
|
|
128
|
-
* Write operator profile (label + owner +
|
|
129
|
-
*
|
|
130
|
-
* @param {{ label: string, owner: string, key?: { type: 'env'|'keyFile', value?: string }|null }} op
|
|
123
|
+
* Write operator profile (label + owner + key pointer). Never stores hex keys.
|
|
124
|
+
* @param {{ label: string, owner: string, key?: { type: 'env'|'keyFile', value?: string } }} op
|
|
131
125
|
* @param {string} [home]
|
|
132
126
|
*/
|
|
133
127
|
export function writeOperator(op, home = clankerHome()) {
|
|
@@ -136,10 +130,8 @@ export function writeOperator(op, home = clankerHome()) {
|
|
|
136
130
|
const out = {
|
|
137
131
|
label: op.label,
|
|
138
132
|
owner: op.owner,
|
|
133
|
+
key: op.key ?? { type: "env", value: "OPERATOR_PRIVATE_KEY" },
|
|
139
134
|
};
|
|
140
|
-
if (op.key != null) {
|
|
141
|
-
out.key = op.key;
|
|
142
|
-
}
|
|
143
135
|
writeFileSync(path, `${JSON.stringify(out, null, 2)}\n`, { mode: 0o600 });
|
|
144
136
|
return { path, operator: out };
|
|
145
137
|
}
|
|
@@ -190,7 +182,7 @@ export function resolveNetwork(argv = [], opts = {}) {
|
|
|
190
182
|
}
|
|
191
183
|
|
|
192
184
|
if (fromBlock == null) {
|
|
193
|
-
fromBlock = isLocalRpc(rpc) ? 0n :
|
|
185
|
+
fromBlock = isLocalRpc(rpc) ? 0n : SEPOLIA_FROM_BLOCK;
|
|
194
186
|
}
|
|
195
187
|
|
|
196
188
|
return {
|
package/lib/resolve.mjs
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { existsSync, readFileSync } from "node:fs";
|
|
6
|
-
import { getAddress } from "viem";
|
|
7
6
|
import { privateKeyToAccount } from "viem/accounts";
|
|
8
7
|
import {
|
|
9
8
|
ANVIL_DEFAULT_PRIVATE_KEY,
|
|
@@ -175,63 +174,8 @@ export function resolveForRead(argv = [], opts = {}) {
|
|
|
175
174
|
if (!network.registry || !/^0x[0-9a-fA-F]{40}$/.test(network.registry)) {
|
|
176
175
|
throw new Error(
|
|
177
176
|
"REGISTRY_ADDRESS or --registry is required (0x + 40 hex). " +
|
|
178
|
-
"Run `clanker init --preset sepolia` or
|
|
177
|
+
"Run `clanker init --preset sepolia` or set registry after `clanker chain deploy`.",
|
|
179
178
|
);
|
|
180
179
|
}
|
|
181
180
|
return network;
|
|
182
181
|
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Resolve address for read-only commands.
|
|
186
|
-
* Order: --address > signing key > operator.json owner > error (point at setup).
|
|
187
|
-
*
|
|
188
|
-
* @param {string[]} argv
|
|
189
|
-
* @param {{ home?: string, env?: NodeJS.ProcessEnv }} [opts]
|
|
190
|
-
* @returns {{ address: string, source: string, network: object }}
|
|
191
|
-
*/
|
|
192
|
-
export function resolveReadIdentity(argv = [], opts = {}) {
|
|
193
|
-
const network = resolveForRead(argv, opts);
|
|
194
|
-
const home = opts.home ?? network.home;
|
|
195
|
-
|
|
196
|
-
let addressFlag = null;
|
|
197
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
198
|
-
if (argv[i] === "--address" && argv[i + 1] && !argv[i + 1].startsWith("--")) {
|
|
199
|
-
addressFlag = argv[++i];
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
if (addressFlag) {
|
|
203
|
-
return {
|
|
204
|
-
address: getAddress(addressFlag),
|
|
205
|
-
source: "--address",
|
|
206
|
-
network,
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
try {
|
|
211
|
-
const resolved = resolveOperatorKey(argv, { ...opts, home });
|
|
212
|
-
return {
|
|
213
|
-
address: resolved.address,
|
|
214
|
-
source: resolved.source,
|
|
215
|
-
network: resolved.network,
|
|
216
|
-
};
|
|
217
|
-
} catch (err) {
|
|
218
|
-
const msg = err?.message ?? String(err);
|
|
219
|
-
if (!/private key required|Anvil account #0|Key file not found|Profile keyFile/i.test(msg)) {
|
|
220
|
-
throw err;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const operator = loadOperator(home);
|
|
225
|
-
if (operator?.owner && /^0x[0-9a-fA-F]{40}$/.test(operator.owner)) {
|
|
226
|
-
return {
|
|
227
|
-
address: getAddress(operator.owner),
|
|
228
|
-
source: "profile owner",
|
|
229
|
-
network,
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
throw new Error(
|
|
234
|
-
"No operator identity configured. Run `clanker setup`, pass --address 0x…, " +
|
|
235
|
-
"or set a signing key (OPERATOR_PRIVATE_KEY / --key-file / operator.json key pointer).",
|
|
236
|
-
);
|
|
237
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clanker-chain/clanker-cli",
|
|
3
|
-
"version": "2026.9.7
|
|
3
|
+
"version": "2026.9.7",
|
|
4
4
|
"description": "CLI for wiring clanker-chain identity and MQTT into OpenClaw and other agentic stacks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -23,8 +23,6 @@
|
|
|
23
23
|
"mint-bot:sepolia": "bash ./scripts/with-sepolia-env.sh mint-bot"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@clack/prompts": "^1.8.0",
|
|
27
|
-
"picocolors": "^1.1.1",
|
|
28
26
|
"viem": "^2.21.0"
|
|
29
27
|
}
|
|
30
28
|
}
|