traderclaw-cli 1.0.101 → 1.0.103
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/gateway-persistence-linux.mjs +15 -4
- package/bin/openclaw-trader.mjs +189 -13
- package/package.json +2 -2
|
@@ -198,23 +198,34 @@ export async function ensureLinuxGatewayPersistence(options = {}) {
|
|
|
198
198
|
let unitEnabled = false;
|
|
199
199
|
try {
|
|
200
200
|
await runSpawn("systemctl", ["--user", "daemon-reload"]);
|
|
201
|
-
await runSpawn("systemctl", ["--user", "enable", unitName]);
|
|
201
|
+
await runSpawn("systemctl", ["--user", "enable", "--now", unitName]);
|
|
202
202
|
unitEnabled = true;
|
|
203
|
-
emit("info", `systemd user unit enabled: ${unitName}`);
|
|
203
|
+
emit("info", `systemd user unit enabled and started: ${unitName}`);
|
|
204
204
|
} catch (err) {
|
|
205
205
|
const msg = err?.stderr || err?.message || String(err);
|
|
206
|
-
errors.push(`systemctl --user enable: ${msg}`);
|
|
206
|
+
errors.push(`systemctl --user enable --now: ${msg}`);
|
|
207
207
|
emit(
|
|
208
208
|
"warn",
|
|
209
|
-
`Could not enable user unit ${unitName} (${msg.trim()}). If the gateway was installed, try: systemctl --user enable ${unitName}`,
|
|
209
|
+
`Could not enable/start user unit ${unitName} (${msg.trim()}). If the gateway was installed, try: systemctl --user enable --now ${unitName}`,
|
|
210
210
|
);
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
let unitActive = false;
|
|
214
|
+
try {
|
|
215
|
+
await runSpawn("systemctl", ["--user", "is-active", unitName]);
|
|
216
|
+
unitActive = true;
|
|
217
|
+
emit("info", `${unitName} is active.`);
|
|
218
|
+
} catch {
|
|
219
|
+
// is-active exits non-zero when inactive; not a hard error
|
|
220
|
+
emit("info", `${unitName} is not yet active (may need: openclaw gateway restart).`);
|
|
221
|
+
}
|
|
222
|
+
|
|
213
223
|
return {
|
|
214
224
|
skipped: false,
|
|
215
225
|
linger: lingerOk,
|
|
216
226
|
unitName,
|
|
217
227
|
unitEnabled,
|
|
228
|
+
unitActive,
|
|
218
229
|
errors: errors.length ? errors : undefined,
|
|
219
230
|
};
|
|
220
231
|
}
|
package/bin/openclaw-trader.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { dirname, join } from "path";
|
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
7
7
|
import { homedir } from "os";
|
|
8
8
|
import { randomUUID, createPrivateKey, sign as cryptoSign } from "crypto";
|
|
9
|
-
import { execFile, execFileSync, execSync } from "child_process";
|
|
9
|
+
import { execFile, execFileSync, execSync, spawnSync } from "child_process";
|
|
10
10
|
import { promisify } from "util";
|
|
11
11
|
import { createServer } from "http";
|
|
12
12
|
import { resolvePluginPackageRoot } from "./resolve-plugin-root.mjs";
|
|
@@ -65,6 +65,9 @@ try {
|
|
|
65
65
|
const VERSION = CLI_VERSION || PLUGIN_VERSION;
|
|
66
66
|
const PLUGIN_ID = "solana-trader";
|
|
67
67
|
const LEGACY_PLUGIN_IDS = ["traderclaw-v1", "solana-traderclaw-v1", "solana-traderclaw"];
|
|
68
|
+
const KAYBA_TRACING_PLUGIN_ID = "kayba-tracing";
|
|
69
|
+
const KAYBA_TRACING_NPM_PACKAGE = "@kayba_ai/openclaw-tracing";
|
|
70
|
+
const KAYBA_TRACING_FOLDER_DEFAULT = "traderclaw-agent";
|
|
68
71
|
const CONFIG_DIR = join(homedir(), ".openclaw");
|
|
69
72
|
const CONFIG_FILE = join(CONFIG_DIR, "openclaw.json");
|
|
70
73
|
const WALLET_PRIVATE_KEY_ENV = "TRADERCLAW_WALLET_PRIVATE_KEY";
|
|
@@ -171,6 +174,53 @@ function extractJson(raw) {
|
|
|
171
174
|
/** Env vars passed to every openclaw CLI invocation to suppress colour output. */
|
|
172
175
|
const NO_COLOR_ENV = { ...process.env, NO_COLOR: "1", FORCE_COLOR: "0" };
|
|
173
176
|
|
|
177
|
+
function delay(ms) {
|
|
178
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** True when OpenClaw / ClawHub reports HTTP 429 or rate limiting (retry installs instead of failing). */
|
|
182
|
+
function isOpenClawClawHubRateLimit(combinedOutput) {
|
|
183
|
+
const t = stripAnsi(String(combinedOutput || "")).toLowerCase();
|
|
184
|
+
return /\b429\b/.test(t) || t.includes("rate limit") || t.includes("too many requests");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Runs `openclaw plugins install … --force` with backoff retries when ClawHub returns 429.
|
|
189
|
+
*/
|
|
190
|
+
async function runOpenclawPluginsInstallWithRetry(installArgs, installSpec) {
|
|
191
|
+
const maxAttempts = 5;
|
|
192
|
+
const baseDelayMs = 12000;
|
|
193
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
194
|
+
try {
|
|
195
|
+
const r = await execFileAsync("openclaw", installArgs, {
|
|
196
|
+
maxBuffer: 15 * 1024 * 1024,
|
|
197
|
+
env: NO_COLOR_ENV,
|
|
198
|
+
});
|
|
199
|
+
if (r.stdout) process.stdout.write(r.stdout);
|
|
200
|
+
if (r.stderr) process.stderr.write(r.stderr);
|
|
201
|
+
return;
|
|
202
|
+
} catch (e) {
|
|
203
|
+
const stdout =
|
|
204
|
+
typeof e.stdout === "string" ? e.stdout : Buffer.isBuffer(e.stdout) ? e.stdout.toString("utf-8") : "";
|
|
205
|
+
const stderr =
|
|
206
|
+
typeof e.stderr === "string" ? e.stderr : Buffer.isBuffer(e.stderr) ? e.stderr.toString("utf-8") : "";
|
|
207
|
+
const combined = `${stdout}${stderr}${e.message || ""}`;
|
|
208
|
+
if (stdout) process.stdout.write(stdout);
|
|
209
|
+
if (stderr) process.stderr.write(stderr);
|
|
210
|
+
const retryable = isOpenClawClawHubRateLimit(combined);
|
|
211
|
+
if (attempt < maxAttempts && retryable) {
|
|
212
|
+
const waitMs = Math.min(baseDelayMs * 2 ** (attempt - 1), 180000);
|
|
213
|
+
printWarn(
|
|
214
|
+
` ClawHub rate limited while installing ${installSpec} (attempt ${attempt}/${maxAttempts}). Waiting ${Math.round(waitMs / 1000)}s, then retrying…`,
|
|
215
|
+
);
|
|
216
|
+
await delay(waitMs);
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
throw e;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
174
224
|
function getCommandOutput(cmd) {
|
|
175
225
|
try {
|
|
176
226
|
return execSync(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], shell: true, maxBuffer: 50 * 1024 * 1024, env: NO_COLOR_ENV }).trim();
|
|
@@ -422,6 +472,48 @@ function setPluginConfig(config, pluginConfig) {
|
|
|
422
472
|
};
|
|
423
473
|
}
|
|
424
474
|
|
|
475
|
+
function setKaybaTracingPluginConfig(config, kaybaApiKey, folder) {
|
|
476
|
+
normalizePluginConfigShape(config);
|
|
477
|
+
if (!config.plugins) config.plugins = {};
|
|
478
|
+
if (!config.plugins.entries) config.plugins.entries = {};
|
|
479
|
+
if (!Array.isArray(config.plugins.allow)) config.plugins.allow = [];
|
|
480
|
+
if (!config.plugins.allow.includes(KAYBA_TRACING_PLUGIN_ID)) {
|
|
481
|
+
config.plugins.allow.push(KAYBA_TRACING_PLUGIN_ID);
|
|
482
|
+
}
|
|
483
|
+
const prev = config.plugins.entries[KAYBA_TRACING_PLUGIN_ID];
|
|
484
|
+
const prevConfig = prev && typeof prev.config === "object" && prev.config !== null ? prev.config : {};
|
|
485
|
+
config.plugins.entries[KAYBA_TRACING_PLUGIN_ID] = {
|
|
486
|
+
enabled: true,
|
|
487
|
+
hooks: { allowConversationAccess: true },
|
|
488
|
+
config: {
|
|
489
|
+
...prevConfig,
|
|
490
|
+
apiKey: kaybaApiKey,
|
|
491
|
+
folder: prevConfig.folder || folder || KAYBA_TRACING_FOLDER_DEFAULT,
|
|
492
|
+
},
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
async function installAndEnableKaybaTracingPlugin() {
|
|
497
|
+
// Best-effort: openclaw plugins install <pkg> + enable <id>. Returns null on success, error message on failure.
|
|
498
|
+
try {
|
|
499
|
+
await execFileAsync("openclaw", ["plugins", "install", KAYBA_TRACING_NPM_PACKAGE], { env: NO_COLOR_ENV });
|
|
500
|
+
} catch (err) {
|
|
501
|
+
const text = `${err?.message || ""}\n${err?.stderr || ""}`.toLowerCase();
|
|
502
|
+
if (!text.includes("already exists") && !text.includes("already installed")) {
|
|
503
|
+
return err instanceof Error ? err.message : String(err);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
try {
|
|
507
|
+
await execFileAsync("openclaw", ["plugins", "enable", KAYBA_TRACING_PLUGIN_ID], { env: NO_COLOR_ENV });
|
|
508
|
+
} catch (err) {
|
|
509
|
+
const text = `${err?.message || ""}\n${err?.stderr || ""}`.toLowerCase();
|
|
510
|
+
if (!text.includes("already enabled")) {
|
|
511
|
+
return err instanceof Error ? err.message : String(err);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
|
|
425
517
|
function getGatewayConfig(config) {
|
|
426
518
|
if (!config || typeof config !== "object") return {};
|
|
427
519
|
if (!config.gateway || typeof config.gateway !== "object") return {};
|
|
@@ -782,6 +874,7 @@ async function cmdSetup(args) {
|
|
|
782
874
|
let forwardTelegramRecipientArg = "";
|
|
783
875
|
let referralCodeArg = "";
|
|
784
876
|
let referralInvalidRetries = 0;
|
|
877
|
+
let kaybaApiKeyArg = "";
|
|
785
878
|
|
|
786
879
|
for (let i = 0; i < args.length; i++) {
|
|
787
880
|
if ((args[i] === "--api-key" || args[i] === "-k") && args[i + 1]) {
|
|
@@ -831,6 +924,9 @@ async function cmdSetup(args) {
|
|
|
831
924
|
if ((args[i] === "--referral-code" || args[i] === "-r") && args[i + 1]) {
|
|
832
925
|
referralCodeArg = args[++i];
|
|
833
926
|
}
|
|
927
|
+
if ((args[i] === "--kayba-key" || args[i] === "--kayba-api-key") && args[i + 1]) {
|
|
928
|
+
kaybaApiKeyArg = args[++i];
|
|
929
|
+
}
|
|
834
930
|
}
|
|
835
931
|
const runtimeWalletPrivateKey = getRuntimeWalletPrivateKey(walletPrivateKey);
|
|
836
932
|
|
|
@@ -1169,12 +1265,30 @@ async function cmdSetup(args) {
|
|
|
1169
1265
|
}
|
|
1170
1266
|
}
|
|
1171
1267
|
|
|
1268
|
+
let kaybaApiKey = (kaybaApiKeyArg || process.env.KAYBA_API_KEY || prevPlugin?.kaybaApiKey || "").trim();
|
|
1269
|
+
if (!kaybaApiKey) {
|
|
1270
|
+
print("\nKayba tracing (optional)...\n");
|
|
1271
|
+
printInfo(" Capture every agent turn — full LLM prompts, tool calls, replies — for observability.");
|
|
1272
|
+
printInfo(" Get a key at https://use.kayba.ai/settings/api-keys, or use one provided by your operator.");
|
|
1273
|
+
kaybaApiKey = (await prompt("Kayba API key (kayba_ak_..., Enter to skip)", "")).trim();
|
|
1274
|
+
} else {
|
|
1275
|
+
printInfo(`\n Reusing Kayba API key: ${maskKey(kaybaApiKey)}`);
|
|
1276
|
+
}
|
|
1277
|
+
if (kaybaApiKey) {
|
|
1278
|
+
pluginConfig.kaybaApiKey = kaybaApiKey;
|
|
1279
|
+
if (!pluginConfig.kaybaFolder) pluginConfig.kaybaFolder = "traderclaw";
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1172
1282
|
print("\nWriting configuration...\n");
|
|
1173
1283
|
|
|
1174
1284
|
const existingConfig = readConfig();
|
|
1175
1285
|
removeLegacyWalletPrivateKey(pluginConfig);
|
|
1176
1286
|
setPluginConfig(existingConfig, pluginConfig);
|
|
1177
1287
|
|
|
1288
|
+
if (kaybaApiKey) {
|
|
1289
|
+
setKaybaTracingPluginConfig(existingConfig, kaybaApiKey, KAYBA_TRACING_FOLDER_DEFAULT);
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1178
1292
|
if (!existingConfig.agents || typeof existingConfig.agents !== "object") {
|
|
1179
1293
|
existingConfig.agents = {};
|
|
1180
1294
|
}
|
|
@@ -1204,6 +1318,17 @@ async function cmdSetup(args) {
|
|
|
1204
1318
|
|
|
1205
1319
|
printSuccess(` Config written to ${CONFIG_FILE}`);
|
|
1206
1320
|
|
|
1321
|
+
if (kaybaApiKey) {
|
|
1322
|
+
print(`\nInstalling ${KAYBA_TRACING_PLUGIN_ID} plugin (one-time)...\n`);
|
|
1323
|
+
const installErr = await installAndEnableKaybaTracingPlugin();
|
|
1324
|
+
if (installErr) {
|
|
1325
|
+
printWarn(` Plugin install failed: ${installErr}`);
|
|
1326
|
+
printWarn(` Finish manually: openclaw plugins install ${KAYBA_TRACING_NPM_PACKAGE} && openclaw plugins enable ${KAYBA_TRACING_PLUGIN_ID}`);
|
|
1327
|
+
} else {
|
|
1328
|
+
printSuccess(` ${KAYBA_TRACING_PLUGIN_ID} installed and enabled (folder: ${KAYBA_TRACING_FOLDER_DEFAULT})`);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1207
1332
|
if (!skipGatewayRegistration) {
|
|
1208
1333
|
print("\nGateway forwarding setup (required for event-driven wakeups)...\n");
|
|
1209
1334
|
|
|
@@ -4195,15 +4320,17 @@ Setup options:
|
|
|
4195
4320
|
--gateway-token, -t Gateway bearer token (defaults to API key)
|
|
4196
4321
|
--telegram-recipient Telegram @username or chat id (aliases: --forward-telegram-chat-id, --telegram-chat-id)
|
|
4197
4322
|
--referral-code, -r Optional referral code for new signups (extra trial time when valid)
|
|
4323
|
+
--kayba-key Kayba API key (kayba_ak_...) — captures every agent turn to your Kayba dashboard.
|
|
4324
|
+
Aliases: --kayba-api-key. Env fallback: KAYBA_API_KEY. Skip with empty value.
|
|
4198
4325
|
--skip-gateway-registration Skip gateway URL registration with orchestrator
|
|
4199
4326
|
--show-api-key Extra hint after signup (full key is always shown once; confirm with API_KEY_STORED)
|
|
4200
4327
|
--show-wallet-private-key Reveal full wallet private key in setup output
|
|
4201
4328
|
--signup Force signup flow (create new account)
|
|
4202
4329
|
--write-gateway-env Write TRADERCLAW_WALLET_PRIVATE_KEY to a systemd EnvironmentFile for the user gateway (Linux)
|
|
4203
|
-
--no-ensure-gateway-persistent Skip automatic Linux loginctl linger + user
|
|
4330
|
+
--no-ensure-gateway-persistent Skip automatic Linux loginctl linger + systemctl --user enable --now after setup
|
|
4204
4331
|
|
|
4205
4332
|
Gateway subcommands:
|
|
4206
|
-
gateway ensure-persistent Linux: enable loginctl linger and
|
|
4333
|
+
gateway ensure-persistent Linux: enable loginctl linger and systemctl --user enable --now for OpenClaw gateway
|
|
4207
4334
|
|
|
4208
4335
|
Login options:
|
|
4209
4336
|
--wallet-private-key <k> Base58 key for wallet proof (runtime only, never saved). Optional in a
|
|
@@ -4240,6 +4367,8 @@ Examples:
|
|
|
4240
4367
|
traderclaw setup --api-key oc_xxx --url https://api.traderclaw.ai
|
|
4241
4368
|
traderclaw setup --gateway-base-url https://gateway.myhost.ts.net
|
|
4242
4369
|
traderclaw setup --telegram-recipient @myusername
|
|
4370
|
+
traderclaw setup --kayba-key kayba_ak_xxx # one-shot Kayba tracing setup (installs kayba-tracing plugin)
|
|
4371
|
+
KAYBA_API_KEY=kayba_ak_xxx traderclaw setup # same via env var
|
|
4243
4372
|
traderclaw login
|
|
4244
4373
|
traderclaw login --force-reauth --wallet-private-key <base58_key>
|
|
4245
4374
|
traderclaw logout
|
|
@@ -4361,9 +4490,27 @@ async function cmdUpdate(args) {
|
|
|
4361
4490
|
`\n Forcing full integration: openclaw plugins install ${installSpec} --force\n` +
|
|
4362
4491
|
" (extension on disk + plugins.installs / integrity.)\n",
|
|
4363
4492
|
);
|
|
4364
|
-
|
|
4493
|
+
await runOpenclawPluginsInstallWithRetry(installArgs, installSpec);
|
|
4365
4494
|
printSuccess(`\n Forced install complete: ${installSpec}.`);
|
|
4366
|
-
} catch {
|
|
4495
|
+
} catch (e) {
|
|
4496
|
+
const out =
|
|
4497
|
+
typeof e.stdout === "string"
|
|
4498
|
+
? e.stdout
|
|
4499
|
+
: Buffer.isBuffer(e.stdout)
|
|
4500
|
+
? e.stdout.toString("utf-8")
|
|
4501
|
+
: "";
|
|
4502
|
+
const err =
|
|
4503
|
+
typeof e.stderr === "string"
|
|
4504
|
+
? e.stderr
|
|
4505
|
+
: Buffer.isBuffer(e.stderr)
|
|
4506
|
+
? e.stderr.toString("utf-8")
|
|
4507
|
+
: "";
|
|
4508
|
+
const blob = `${out}${err}${e.message || ""}`;
|
|
4509
|
+
if (isOpenClawClawHubRateLimit(blob)) {
|
|
4510
|
+
printWarn(
|
|
4511
|
+
` ClawHub rate limit persisted after retries — plugin files may still match the version from "plugins update" until this step succeeds.`,
|
|
4512
|
+
);
|
|
4513
|
+
}
|
|
4367
4514
|
printError(`"openclaw plugins install ${installSpec} --force" failed. Try manually:`);
|
|
4368
4515
|
print(` openclaw plugins install ${installSpec} --force`);
|
|
4369
4516
|
process.exit(1);
|
|
@@ -4388,17 +4535,46 @@ async function cmdUpdate(args) {
|
|
|
4388
4535
|
}
|
|
4389
4536
|
|
|
4390
4537
|
if (dryRun) {
|
|
4391
|
-
print(`\n [dry-run] Would run: openclaw gateway restart\n`);
|
|
4538
|
+
print(`\n [dry-run] Would run: systemctl --user enable --now + restart (Linux) or openclaw gateway restart\n`);
|
|
4392
4539
|
} else {
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4540
|
+
const { isLinuxGatewayPersistenceEligible, ensureLinuxGatewayPersistence, resolveGatewayUnitNameFromStatusJson, readOpenclawGatewayStatusJson } = await import("./gateway-persistence-linux.mjs");
|
|
4541
|
+
if (isLinuxGatewayPersistenceEligible()) {
|
|
4542
|
+
print("\n Gateway persistence (Linux)...\n");
|
|
4543
|
+
let unitName = "openclaw-gateway.service";
|
|
4544
|
+
try {
|
|
4545
|
+
const statusJson = readOpenclawGatewayStatusJson();
|
|
4546
|
+
unitName = resolveGatewayUnitNameFromStatusJson(statusJson);
|
|
4547
|
+
await ensureLinuxGatewayPersistence({
|
|
4548
|
+
emitLog: (level, text) => {
|
|
4549
|
+
if (level === "warn") printWarn(` ${text}`);
|
|
4550
|
+
else printInfo(` ${text}`);
|
|
4551
|
+
},
|
|
4552
|
+
});
|
|
4553
|
+
} catch (err) {
|
|
4554
|
+
printWarn(` Gateway persistence (optional): ${err.message || err}`);
|
|
4555
|
+
}
|
|
4396
4556
|
print("\n Restarting gateway...\n");
|
|
4397
4557
|
try {
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4558
|
+
const r = spawnSync("systemctl", ["--user", "restart", unitName], { stdio: "inherit" });
|
|
4559
|
+
if (r.status === 0) {
|
|
4560
|
+
printSuccess(` Gateway restarted (systemctl --user restart ${unitName}).`);
|
|
4561
|
+
} else {
|
|
4562
|
+
printWarn(` systemctl --user restart returned ${r.status}. Try: systemctl --user restart ${unitName}`);
|
|
4563
|
+
}
|
|
4564
|
+
} catch (err) {
|
|
4565
|
+
printWarn(` systemctl --user restart: ${err.message || err}. Try manually: systemctl --user restart ${unitName}`);
|
|
4566
|
+
}
|
|
4567
|
+
} else {
|
|
4568
|
+
if (!commandExists("openclaw")) {
|
|
4569
|
+
printWarn("\n Skipping gateway restart: openclaw not in PATH. After fixing PATH: openclaw gateway restart");
|
|
4570
|
+
} else {
|
|
4571
|
+
print("\n Restarting gateway...\n");
|
|
4572
|
+
try {
|
|
4573
|
+
execFileSync("openclaw", ["gateway", "restart"], { stdio: "inherit" });
|
|
4574
|
+
printSuccess(" Gateway restarted.");
|
|
4575
|
+
} catch {
|
|
4576
|
+
printWarn(" Gateway restart returned non-zero. Try manually: openclaw gateway restart");
|
|
4577
|
+
}
|
|
4402
4578
|
}
|
|
4403
4579
|
}
|
|
4404
4580
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "traderclaw-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.103",
|
|
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.103"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"traderclaw",
|