traderclaw-cli 1.0.84 → 1.0.86
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/installer-step-engine.mjs +28 -9
- package/bin/openclaw-trader.mjs +85 -3
- package/package.json +2 -2
|
@@ -2214,21 +2214,38 @@ export class InstallerStepEngine {
|
|
|
2214
2214
|
}
|
|
2215
2215
|
|
|
2216
2216
|
buildSetupHandoff() {
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2217
|
+
// Shell-safe single-quote wrapper: wraps value in '…' and escapes any embedded single quotes.
|
|
2218
|
+
const shQuote = (v) => `'${String(v).replace(/'/g, "'\\''")}'`;
|
|
2219
|
+
|
|
2220
|
+
const cliName = this.modeConfig.cliName;
|
|
2221
|
+
const orchestratorUrl = this.options.orchestratorUrl || "https://api.traderclaw.ai";
|
|
2222
|
+
const apiKey = String(this.options.apiKey || "").trim();
|
|
2223
|
+
|
|
2224
|
+
// Build args in the user-facing convention:
|
|
2225
|
+
// traderclaw setup --api-key '…' --url '…' [--gateway-base-url '…'] [--skip-gateway-registration] [--referral-code '…']
|
|
2226
|
+
const parts = [cliName, "setup"];
|
|
2227
|
+
|
|
2228
|
+
if (apiKey) {
|
|
2229
|
+
parts.push("--api-key", shQuote(apiKey));
|
|
2220
2230
|
}
|
|
2231
|
+
|
|
2232
|
+
parts.push("--url", shQuote(orchestratorUrl));
|
|
2233
|
+
|
|
2221
2234
|
const gatewayBaseUrl = this.options.gatewayBaseUrl || this.state.detected.funnelUrl || "";
|
|
2222
2235
|
if (this.options.lane === "event-driven" && gatewayBaseUrl) {
|
|
2223
|
-
|
|
2236
|
+
parts.push("--gateway-base-url", shQuote(gatewayBaseUrl));
|
|
2237
|
+
}
|
|
2238
|
+
|
|
2239
|
+
if (this.options.lane !== "event-driven") {
|
|
2240
|
+
parts.push("--skip-gateway-registration");
|
|
2224
2241
|
}
|
|
2225
2242
|
|
|
2226
2243
|
const ref = String(this.options.referralCode || "").trim();
|
|
2227
2244
|
if (ref) {
|
|
2228
|
-
|
|
2245
|
+
parts.push("--referral-code", shQuote(ref));
|
|
2229
2246
|
}
|
|
2230
2247
|
|
|
2231
|
-
const command =
|
|
2248
|
+
const command = parts.join(" ");
|
|
2232
2249
|
const docs =
|
|
2233
2250
|
"https://docs.traderclaw.ai/docs/installation#troubleshooting-session-expired-auth-errors-or-the-agent-logged-out";
|
|
2234
2251
|
return {
|
|
@@ -2236,11 +2253,13 @@ export class InstallerStepEngine {
|
|
|
2236
2253
|
command,
|
|
2237
2254
|
title: "Ready to launch your agentic trading desk",
|
|
2238
2255
|
message:
|
|
2239
|
-
"Core install is complete.
|
|
2240
|
-
"
|
|
2256
|
+
"Core install is complete. Run the command below in your VPS shell to complete authentication. " +
|
|
2257
|
+
"The wallet private key is intentionally omitted — if your account has a linked wallet, traderclaw setup will prompt for it securely in the terminal (hidden input, key is never saved or sent). " +
|
|
2258
|
+
"For automation or non-interactive environments use --wallet-private-key or the TRADERCLAW_WALLET_PRIVATE_KEY env var instead. " +
|
|
2259
|
+
"After setup, configure TRADERCLAW_WALLET_PRIVATE_KEY for the OpenClaw gateway service (systemd) so the bot can sign challenges at runtime — not only in your SSH session. See " +
|
|
2241
2260
|
docs,
|
|
2242
2261
|
hint:
|
|
2243
|
-
"Run the command in terminal
|
|
2262
|
+
"Run the command in your terminal. If wallet proof is required, you will be prompted for the private key with hidden input. Then restart the gateway.",
|
|
2244
2263
|
restartCommand: "openclaw gateway restart",
|
|
2245
2264
|
};
|
|
2246
2265
|
}
|
package/bin/openclaw-trader.mjs
CHANGED
|
@@ -214,6 +214,79 @@ async function confirm(question) {
|
|
|
214
214
|
return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
/**
|
|
218
|
+
* Prompt for the wallet private key with hidden input (no echo) when running in a TTY.
|
|
219
|
+
* Falls back to a visible prompt with a warning if raw mode is unavailable.
|
|
220
|
+
* Returns an empty string if the user presses Enter with no input.
|
|
221
|
+
*/
|
|
222
|
+
async function promptWalletPrivateKeyHidden() {
|
|
223
|
+
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
224
|
+
if (!isTTY) return "";
|
|
225
|
+
|
|
226
|
+
print(" Your trading wallet private key is required to prove ownership of the linked wallet.");
|
|
227
|
+
print(" It is used only to sign a one-time challenge locally — it is NEVER sent to any server");
|
|
228
|
+
print(" and is NEVER written to openclaw.json or any file.");
|
|
229
|
+
print(" For automation, use --wallet-private-key or the TRADERCLAW_WALLET_PRIVATE_KEY env var instead.\n");
|
|
230
|
+
|
|
231
|
+
return new Promise((resolve) => {
|
|
232
|
+
let input = "";
|
|
233
|
+
let rawEnabled = false;
|
|
234
|
+
|
|
235
|
+
const cleanup = () => {
|
|
236
|
+
try {
|
|
237
|
+
if (rawEnabled && process.stdin.isTTY) {
|
|
238
|
+
process.stdin.setRawMode(false);
|
|
239
|
+
}
|
|
240
|
+
} catch {
|
|
241
|
+
// ignore
|
|
242
|
+
}
|
|
243
|
+
process.stdin.pause();
|
|
244
|
+
process.stdin.removeAllListeners("data");
|
|
245
|
+
process.stdin.removeAllListeners("end");
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
process.stdin.setRawMode(true);
|
|
250
|
+
rawEnabled = true;
|
|
251
|
+
} catch {
|
|
252
|
+
// raw mode unavailable — fall through to visible prompt
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (rawEnabled) {
|
|
256
|
+
process.stdout.write(" Wallet private key (hidden, press Enter when done): ");
|
|
257
|
+
process.stdin.resume();
|
|
258
|
+
process.stdin.setEncoding("utf8");
|
|
259
|
+
|
|
260
|
+
process.stdin.on("data", (ch) => {
|
|
261
|
+
if (ch === "\r" || ch === "\n") {
|
|
262
|
+
process.stdout.write("\n");
|
|
263
|
+
cleanup();
|
|
264
|
+
resolve(input.trim());
|
|
265
|
+
} else if (ch === "\u0003") {
|
|
266
|
+
// Ctrl-C
|
|
267
|
+
process.stdout.write("\n");
|
|
268
|
+
cleanup();
|
|
269
|
+
resolve("");
|
|
270
|
+
} else if (ch === "\u007f" || ch === "\b") {
|
|
271
|
+
// backspace
|
|
272
|
+
if (input.length > 0) input = input.slice(0, -1);
|
|
273
|
+
} else {
|
|
274
|
+
input += ch;
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
process.stdin.once("end", () => {
|
|
279
|
+
cleanup();
|
|
280
|
+
resolve(input.trim());
|
|
281
|
+
});
|
|
282
|
+
} else {
|
|
283
|
+
// Raw mode unavailable; warn and fall back to visible prompt.
|
|
284
|
+
printWarn(" Note: terminal does not support hidden input — key will be visible as you type.");
|
|
285
|
+
prompt(" Wallet private key", "").then((val) => resolve(val.trim()));
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
217
290
|
async function httpRequest(url, opts = {}) {
|
|
218
291
|
const controller = new AbortController();
|
|
219
292
|
const timeoutId = setTimeout(() => controller.abort(), opts.timeout ?? 10000);
|
|
@@ -640,10 +713,14 @@ async function establishSession(orchestratorUrl, pluginConfig, walletPrivateKeyI
|
|
|
640
713
|
|
|
641
714
|
if (challenge.walletProofRequired) {
|
|
642
715
|
printWarn(" Wallet proof required — this account already has a wallet.");
|
|
643
|
-
|
|
716
|
+
let walletPrivateKey = getRuntimeWalletPrivateKey(walletPrivateKeyInput);
|
|
717
|
+
if (!walletPrivateKey) {
|
|
718
|
+
walletPrivateKey = await promptWalletPrivateKeyHidden();
|
|
719
|
+
}
|
|
644
720
|
if (!walletPrivateKey) {
|
|
645
721
|
printError(` Wallet private key not available. Cannot prove wallet ownership.`);
|
|
646
722
|
printError(` Provide it via --wallet-private-key or env ${WALLET_PRIVATE_KEY_ENV} for local signing.`);
|
|
723
|
+
printError(` If running interactively (TTY), you will be prompted automatically when proof is required.`);
|
|
647
724
|
printSessionTroubleshootingHint();
|
|
648
725
|
throw new Error("Wallet proof required but no private key configured.");
|
|
649
726
|
}
|
|
@@ -4091,7 +4168,11 @@ Setup options:
|
|
|
4091
4168
|
--api-key, -k API key (skip interactive prompt)
|
|
4092
4169
|
--url, -u Orchestrator URL (skip interactive prompt)
|
|
4093
4170
|
--user-id External user ID for signup
|
|
4094
|
-
--wallet-private-key
|
|
4171
|
+
--wallet-private-key Base58 private key for wallet proof (runtime only, never saved to disk).
|
|
4172
|
+
Optional: when omitted in a TTY session, traderclaw will prompt for it
|
|
4173
|
+
interactively with hidden input if the server requires wallet proof.
|
|
4174
|
+
Required when running non-interactively (scripts, CI) — use env
|
|
4175
|
+
TRADERCLAW_WALLET_PRIVATE_KEY for cleaner shell history.
|
|
4095
4176
|
--gateway-base-url, -g Gateway public HTTPS URL for orchestrator callbacks
|
|
4096
4177
|
--gateway-token, -t Gateway bearer token (defaults to API key)
|
|
4097
4178
|
--telegram-recipient Telegram @username or chat id (aliases: --forward-telegram-chat-id, --telegram-chat-id)
|
|
@@ -4107,7 +4188,8 @@ Gateway subcommands:
|
|
|
4107
4188
|
gateway ensure-persistent Linux: enable loginctl linger and systemd --user unit for OpenClaw gateway
|
|
4108
4189
|
|
|
4109
4190
|
Login options:
|
|
4110
|
-
--wallet-private-key <k> Base58 key for wallet proof
|
|
4191
|
+
--wallet-private-key <k> Base58 key for wallet proof (runtime only, never saved). Optional in a
|
|
4192
|
+
TTY session — traderclaw will prompt with hidden input if proof is needed.
|
|
4111
4193
|
--force-reauth Clear refresh token and run full API challenge (use after logout or to rotate session)
|
|
4112
4194
|
|
|
4113
4195
|
Config subcommands:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "traderclaw-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.86",
|
|
4
4
|
"description": "Global TraderClaw CLI (install --wizard, setup, precheck). Installs solana-traderclaw as a dependency for OpenClaw plugin files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"node": ">=22"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"solana-traderclaw": "^1.0.
|
|
20
|
+
"solana-traderclaw": "^1.0.86"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"traderclaw",
|