traderclaw-v1 1.0.3 → 1.0.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.
@@ -6,7 +6,7 @@ import { join } from "path";
6
6
  import { homedir } from "os";
7
7
  import { randomUUID, createPrivateKey, sign as cryptoSign } from "crypto";
8
8
 
9
- const VERSION = "2.0.0";
9
+ const VERSION = "1.0.4";
10
10
  const PLUGIN_ID = "solana-trader";
11
11
  const CONFIG_DIR = join(homedir(), ".openclaw");
12
12
  const CONFIG_FILE = join(CONFIG_DIR, "openclaw.json");
@@ -138,6 +138,49 @@ function setPluginConfig(config, pluginConfig) {
138
138
  };
139
139
  }
140
140
 
141
+ function extractWalletId(payload) {
142
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) return null;
143
+ if (typeof payload.id === "string" || typeof payload.id === "number") return String(payload.id);
144
+ if (typeof payload.walletId === "string" || typeof payload.walletId === "number") return String(payload.walletId);
145
+ if (payload.wallet && typeof payload.wallet === "object" && !Array.isArray(payload.wallet)) {
146
+ if (typeof payload.wallet.id === "string" || typeof payload.wallet.id === "number") return String(payload.wallet.id);
147
+ if (typeof payload.wallet.walletId === "string" || typeof payload.wallet.walletId === "number") return String(payload.wallet.walletId);
148
+ }
149
+ if (payload.data && typeof payload.data === "object" && !Array.isArray(payload.data)) {
150
+ if (typeof payload.data.id === "string" || typeof payload.data.id === "number") return String(payload.data.id);
151
+ if (typeof payload.data.walletId === "string" || typeof payload.data.walletId === "number") return String(payload.data.walletId);
152
+ }
153
+ return null;
154
+ }
155
+
156
+ function extractWalletKeys(payload) {
157
+ const scopes = [];
158
+ if (payload && typeof payload === "object" && !Array.isArray(payload)) {
159
+ scopes.push(payload);
160
+ if (payload.wallet && typeof payload.wallet === "object" && !Array.isArray(payload.wallet)) {
161
+ scopes.push(payload.wallet);
162
+ }
163
+ if (payload.data && typeof payload.data === "object" && !Array.isArray(payload.data)) {
164
+ scopes.push(payload.data);
165
+ }
166
+ }
167
+
168
+ const pick = (keys) => {
169
+ for (const scope of scopes) {
170
+ for (const key of keys) {
171
+ const val = scope[key];
172
+ if (typeof val === "string" && val.length > 0) return val;
173
+ }
174
+ }
175
+ return undefined;
176
+ };
177
+
178
+ return {
179
+ publicKey: pick(["walletPublicKey", "publicKey", "address"]),
180
+ privateKey: pick(["walletPrivateKey", "privateKey", "secretKey"]),
181
+ };
182
+ }
183
+
141
184
  const BS58_CHARS = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
142
185
 
143
186
  function b58Decode(str) {
@@ -334,6 +377,9 @@ async function cmdSetup(args) {
334
377
  let apiKey = "";
335
378
  let orchestratorUrl = "";
336
379
  let externalUserId = "";
380
+ let walletPrivateKey = "";
381
+ let showApiKey = false;
382
+ let showWalletPrivateKey = false;
337
383
  let doSignupFlow = false;
338
384
 
339
385
  for (let i = 0; i < args.length; i++) {
@@ -346,6 +392,15 @@ async function cmdSetup(args) {
346
392
  if ((args[i] === "--user-id") && args[i + 1]) {
347
393
  externalUserId = args[++i];
348
394
  }
395
+ if (args[i] === "--wallet-private-key" && args[i + 1]) {
396
+ walletPrivateKey = args[++i];
397
+ }
398
+ if (args[i] === "--show-api-key") {
399
+ showApiKey = true;
400
+ }
401
+ if (args[i] === "--show-wallet-private-key") {
402
+ showWalletPrivateKey = true;
403
+ }
349
404
  if (args[i] === "--signup") {
350
405
  doSignupFlow = true;
351
406
  }
@@ -376,6 +431,7 @@ async function cmdSetup(args) {
376
431
  apiKey = signupResult.apiKey;
377
432
  printSuccess(` Signup successful!`);
378
433
  printInfo(` API Key: ${maskKey(apiKey)}`);
434
+ if (showApiKey) printWarn(` Full API Key: ${apiKey}`);
379
435
  printInfo(` Tier: ${signupResult.tier}`);
380
436
  printInfo(` Scopes: ${signupResult.scopes.join(", ")}`);
381
437
  } catch (err) {
@@ -398,6 +454,7 @@ async function cmdSetup(args) {
398
454
  apiTimeout: 30000,
399
455
  refreshToken: undefined,
400
456
  walletPublicKey: undefined,
457
+ walletPrivateKey: walletPrivateKey || undefined,
401
458
  };
402
459
 
403
460
  let sessionTokens;
@@ -437,6 +494,7 @@ async function cmdSetup(args) {
437
494
 
438
495
  let walletId = null;
439
496
  let walletLabel = "";
497
+ let createdNewWallet = false;
440
498
 
441
499
  try {
442
500
  const walletsRes = await httpRequest(`${orchestratorUrl}/api/wallets`, { accessToken });
@@ -453,11 +511,18 @@ async function cmdSetup(args) {
453
511
  walletLabel = await prompt("Wallet label", "Trading Wallet");
454
512
  const createRes = await httpRequest(`${orchestratorUrl}/api/wallet/create`, {
455
513
  method: "POST",
456
- body: { label: walletLabel, strategyProfile: "aggressive" },
514
+ body: { label: walletLabel, strategyProfile: "aggressive", includePrivateKey: true },
457
515
  accessToken,
458
516
  });
459
517
  if (createRes.ok) {
460
- walletId = createRes.data.id;
518
+ createdNewWallet = true;
519
+ walletId = extractWalletId(createRes.data);
520
+ if (!walletId) {
521
+ throw new Error(`Wallet create response missing wallet ID: ${JSON.stringify(createRes.data)}`);
522
+ }
523
+ const keys = extractWalletKeys(createRes.data);
524
+ if (keys.publicKey) pluginConfig.walletPublicKey = keys.publicKey;
525
+ if (keys.privateKey && !pluginConfig.walletPrivateKey) pluginConfig.walletPrivateKey = keys.privateKey;
461
526
  printSuccess(` Wallet created (ID: ${walletId})`);
462
527
  } else {
463
528
  printError("Failed to create wallet");
@@ -467,12 +532,16 @@ async function cmdSetup(args) {
467
532
  } else {
468
533
  const idx = parseInt(choice, 10) - 1;
469
534
  if (idx >= 0 && idx < wallets.length) {
470
- walletId = wallets[idx].id;
535
+ walletId = extractWalletId(wallets[idx]) || String(wallets[idx].id);
471
536
  walletLabel = wallets[idx].label || "Unnamed";
537
+ const keys = extractWalletKeys(wallets[idx]);
538
+ if (keys.publicKey) pluginConfig.walletPublicKey = keys.publicKey;
472
539
  printSuccess(` Using wallet: ${walletLabel} (ID: ${walletId})`);
473
540
  } else {
474
- walletId = wallets[0].id;
541
+ walletId = extractWalletId(wallets[0]) || String(wallets[0].id);
475
542
  walletLabel = wallets[0].label || "Unnamed";
543
+ const keys = extractWalletKeys(wallets[0]);
544
+ if (keys.publicKey) pluginConfig.walletPublicKey = keys.publicKey;
476
545
  printSuccess(` Using wallet: ${walletLabel} (ID: ${walletId})`);
477
546
  }
478
547
  }
@@ -481,11 +550,18 @@ async function cmdSetup(args) {
481
550
  walletLabel = await prompt("Wallet label", "Trading Wallet");
482
551
  const createRes = await httpRequest(`${orchestratorUrl}/api/wallet/create`, {
483
552
  method: "POST",
484
- body: { label: walletLabel, strategyProfile: "aggressive" },
553
+ body: { label: walletLabel, strategyProfile: "aggressive", includePrivateKey: true },
485
554
  accessToken,
486
555
  });
487
556
  if (createRes.ok) {
488
- walletId = createRes.data.id;
557
+ createdNewWallet = true;
558
+ walletId = extractWalletId(createRes.data);
559
+ if (!walletId) {
560
+ throw new Error(`Wallet create response missing wallet ID: ${JSON.stringify(createRes.data)}`);
561
+ }
562
+ const keys = extractWalletKeys(createRes.data);
563
+ if (keys.publicKey) pluginConfig.walletPublicKey = keys.publicKey;
564
+ if (keys.privateKey && !pluginConfig.walletPrivateKey) pluginConfig.walletPrivateKey = keys.privateKey;
489
565
  printSuccess(` Wallet created (ID: ${walletId})`);
490
566
  } else {
491
567
  printError("Failed to create wallet");
@@ -509,13 +585,39 @@ async function cmdSetup(args) {
509
585
 
510
586
  printSuccess(` Config written to ${CONFIG_FILE}`);
511
587
 
588
+ if (createdNewWallet) {
589
+ print("\n" + "=".repeat(60));
590
+ printWarn(" IMPORTANT: New wallet credentials");
591
+ print("=".repeat(60));
592
+ print(` Wallet Public Key: ${pluginConfig.walletPublicKey || "not returned by API"}`);
593
+ if (pluginConfig.walletPrivateKey) {
594
+ printWarn(` Wallet Private Key: ${pluginConfig.walletPrivateKey}`);
595
+ printWarn(" Save this private key now in a secure password manager.");
596
+ printWarn(" You may not be able to retrieve this private key again.");
597
+ } else {
598
+ printWarn(" Wallet private key was not returned by the API.");
599
+ printWarn(" If this is expected custody behavior, backup via your wallet provider.");
600
+ }
601
+
602
+ if (pluginConfig.walletPrivateKey) {
603
+ const ack = await prompt("Type BACKED_UP to continue", "");
604
+ if (ack !== "BACKED_UP") {
605
+ printError("Backup confirmation not provided. Aborting setup to prevent key loss.");
606
+ process.exit(1);
607
+ }
608
+ printSuccess(" Backup confirmation received.");
609
+ }
610
+ }
611
+
512
612
  print("\n" + "=".repeat(60));
513
613
  printSuccess("\n Setup complete!\n");
514
614
  print("=".repeat(60));
515
615
  print(`
516
616
  Orchestrator: ${orchestratorUrl}
517
617
  Wallet: ${walletLabel} (ID: ${walletId})
518
- API Key: ${maskKey(apiKey)}
618
+ Wallet PubKey: ${pluginConfig.walletPublicKey || "not set"}
619
+ Wallet PrivKey:${pluginConfig.walletPrivateKey ? (createdNewWallet || showWalletPrivateKey ? " " + pluginConfig.walletPrivateKey : " " + maskKey(pluginConfig.walletPrivateKey)) : " not set"}
620
+ API Key: ${showApiKey ? apiKey : maskKey(apiKey)}
519
621
  Session: Active (tier: ${sessionTokens.session?.tier || "?"})
520
622
  Config: ${CONFIG_FILE}
521
623
  `);
@@ -748,6 +850,7 @@ async function cmdConfig(subArgs) {
748
850
  print(` API Key: ${pluginConfig.apiKey ? maskKey(pluginConfig.apiKey) : "not set"}`);
749
851
  print(` Refresh Token: ${pluginConfig.refreshToken ? maskKey(pluginConfig.refreshToken) : "not set"}`);
750
852
  print(` Wallet Pub Key: ${pluginConfig.walletPublicKey || "not set"}`);
853
+ print(` Wallet Priv Key: ${pluginConfig.walletPrivateKey ? maskKey(pluginConfig.walletPrivateKey) : "not set"}`);
751
854
  print(` API Timeout: ${pluginConfig.apiTimeout || 30000}ms`);
752
855
  print("=".repeat(45));
753
856
  print("");
@@ -835,6 +938,9 @@ Setup options:
835
938
  --api-key, -k API key (skip interactive prompt)
836
939
  --url, -u Orchestrator URL (skip interactive prompt)
837
940
  --user-id External user ID for signup
941
+ --wallet-private-key Optional base58 private key for wallet proof flow
942
+ --show-api-key Reveal full API key in setup output
943
+ --show-wallet-private-key Reveal full wallet private key in setup output
838
944
  --signup Force signup flow (create new account)
839
945
 
840
946
  Config subcommands:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "traderclaw-v1",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "TraderClaw V1 — autonomous Solana memecoin trading agent plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",