traderclaw-cli 1.0.62 → 1.0.63

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.
@@ -1503,6 +1503,7 @@ export class InstallerStepEngine {
1503
1503
  xAccessTokenCtoSecret: typeof options.xAccessTokenCtoSecret === "string" ? options.xAccessTokenCtoSecret : "",
1504
1504
  xAccessTokenIntern: typeof options.xAccessTokenIntern === "string" ? options.xAccessTokenIntern : "",
1505
1505
  xAccessTokenInternSecret: typeof options.xAccessTokenInternSecret === "string" ? options.xAccessTokenInternSecret : "",
1506
+ referralCode: typeof options.referralCode === "string" ? options.referralCode.trim() : "",
1506
1507
  };
1507
1508
  this.hooks = {
1508
1509
  onStepEvent: typeof hooks.onStepEvent === "function" ? hooks.onStepEvent : () => {},
@@ -1788,6 +1789,11 @@ export class InstallerStepEngine {
1788
1789
  args.push("--gateway-base-url", gatewayBaseUrl);
1789
1790
  }
1790
1791
 
1792
+ const ref = String(this.options.referralCode || "").trim();
1793
+ if (ref) {
1794
+ args.push("--referral-code", ref);
1795
+ }
1796
+
1791
1797
  const command = [this.modeConfig.cliName, ...args].join(" ");
1792
1798
  const docs =
1793
1799
  "https://docs.traderclaw.ai/docs/installation#troubleshooting-session-expired-auth-errors-or-the-agent-logged-out";
@@ -520,15 +520,22 @@ function signChallengeLocally(challengeText, privateKeyBase58) {
520
520
  return b58Encode(new Uint8Array(sig));
521
521
  }
522
522
 
523
- async function doSignup(orchestratorUrl, externalUserId) {
523
+ async function doSignup(orchestratorUrl, externalUserId, referralCode = "") {
524
524
  printInfo(` Signing up as: ${externalUserId}`);
525
+ const body = { externalUserId };
526
+ const ref = String(referralCode || "").trim();
527
+ if (ref) body.referralCode = ref;
525
528
  const res = await httpRequest(`${orchestratorUrl}/api/auth/signup`, {
526
529
  method: "POST",
527
- body: { externalUserId },
530
+ body,
528
531
  });
529
532
 
530
533
  if (!res.ok) {
531
- throw new Error(`Signup failed (HTTP ${res.status}): ${JSON.stringify(res.data)}`);
534
+ const payload = res.data && typeof res.data === "object" ? res.data : {};
535
+ const apiMsg = typeof payload.message === "string" ? payload.message : JSON.stringify(res.data);
536
+ const err = new Error(`Signup failed (HTTP ${res.status}): ${apiMsg}`);
537
+ if (typeof payload.code === "string") err.code = payload.code;
538
+ throw err;
532
539
  }
533
540
 
534
541
  return res.data;
@@ -700,6 +707,8 @@ async function cmdSetup(args) {
700
707
  let noEnsureGatewayPersistent = false;
701
708
  let signupRecoverySecret = undefined;
702
709
  let forwardTelegramRecipientArg = "";
710
+ let referralCodeArg = "";
711
+ let referralInvalidRetries = 0;
703
712
 
704
713
  for (let i = 0; i < args.length; i++) {
705
714
  if ((args[i] === "--api-key" || args[i] === "-k") && args[i + 1]) {
@@ -746,6 +755,9 @@ async function cmdSetup(args) {
746
755
  ) {
747
756
  forwardTelegramRecipientArg = args[++i];
748
757
  }
758
+ if ((args[i] === "--referral-code" || args[i] === "-r") && args[i + 1]) {
759
+ referralCodeArg = args[++i];
760
+ }
749
761
  }
750
762
  const runtimeWalletPrivateKey = getRuntimeWalletPrivateKey(walletPrivateKey);
751
763
 
@@ -763,6 +775,16 @@ async function cmdSetup(args) {
763
775
  }
764
776
  }
765
777
 
778
+ if (doSignupFlow && !referralCodeArg) {
779
+ printInfo(
780
+ "\n Optional: enter a referral code for bonus access time (24h extra when valid). Press Enter to skip.\n",
781
+ );
782
+ printInfo(
783
+ " Benefits: extra trial time now; referring others later earns +8h per user who completes at least one trade with the agent.\n",
784
+ );
785
+ referralCodeArg = await prompt("Referral code (optional)", "");
786
+ }
787
+
766
788
  if (doSignupFlow) {
767
789
  print("\n Signing up for a new account...\n");
768
790
  if (!externalUserId) {
@@ -771,7 +793,7 @@ async function cmdSetup(args) {
771
793
 
772
794
  for (let signupAttempt = 0; ; signupAttempt++) {
773
795
  try {
774
- const signupResult = await doSignup(orchestratorUrl, externalUserId);
796
+ const signupResult = await doSignup(orchestratorUrl, externalUserId, referralCodeArg);
775
797
  apiKey = signupResult.apiKey;
776
798
  if (signupResult.recoverySecret) {
777
799
  signupRecoverySecret = signupResult.recoverySecret;
@@ -783,6 +805,22 @@ async function cmdSetup(args) {
783
805
  break;
784
806
  } catch (err) {
785
807
  const msg = err.message || String(err);
808
+ const apiCode = err.code;
809
+ const referralRejected =
810
+ apiCode === "REFERRAL_CODE_INVALID" ||
811
+ msg.includes("REFERRAL_CODE_INVALID") ||
812
+ msg.includes("Unknown referral code");
813
+ if (referralRejected) {
814
+ referralInvalidRetries += 1;
815
+ if (referralInvalidRetries > 30) {
816
+ printError("Too many invalid referral attempts. Aborting.");
817
+ process.exit(1);
818
+ }
819
+ printWarn(" That referral code was not accepted (unknown or invalid).");
820
+ printInfo(" Leave it blank or enter a different code, then try again.");
821
+ referralCodeArg = await prompt("Referral code (optional, leave empty to skip)", "");
822
+ continue;
823
+ }
786
824
  if (msg.includes("SIGNUP_ALREADY_COMPLETED") || msg.includes("409")) {
787
825
  printWarn(` User "${externalUserId}" is already registered.`);
788
826
  if (signupAttempt >= 2) {
@@ -2176,6 +2214,7 @@ function wizardHtml(defaults) {
2176
2214
  .spinner { width:14px; height:14px; border:2px solid #334a87; border-top-color:#8daeff; border-radius:50%; animation:spin 0.8s linear infinite; flex:0 0 auto; }
2177
2215
  .muted a { color:#9fd3ff; }
2178
2216
  .muted a:hover { color:#c5e5ff; }
2217
+ .info-dot { display:inline-flex; align-items:center; justify-content:center; width:18px; height:18px; border-radius:50%; background:#22315a; color:#9cb0de; font-size:11px; font-weight:700; cursor:help; flex-shrink:0; }
2179
2218
  @keyframes spin { to { transform:rotate(360deg); } }
2180
2219
  </style>
2181
2220
  </head>
@@ -2253,6 +2292,13 @@ function wizardHtml(defaults) {
2253
2292
  <p class="muted">Already have a TraderClaw account? Paste your API key here. New users: leave empty.</p>
2254
2293
  </div>
2255
2294
  </div>
2295
+ <div style="margin-top:12px;">
2296
+ <label style="display:flex;align-items:center;gap:8px;">Referral code (optional)
2297
+ <span class="info-dot" title="Included access: 24 hours for every new account. Add a valid referral code for an extra 24 hours. Refer others: when they complete at least one trade with the agent, you earn +8 hours per active referral. When your access window ends, you will need to stake or keep referring to continue.">i</span>
2298
+ </label>
2299
+ <input id="referralCode" type="text" maxlength="16" autocomplete="off" placeholder="e.g. ABCD1234" />
2300
+ <p class="muted">If you have a friend’s code, enter it here. The setup command below will include it for <code>traderclaw setup</code>. If the server rejects the code, clear this field or fix it and copy the updated command — or run <code>traderclaw setup</code> again and enter a valid code or leave referral blank when prompted.</p>
2301
+ </div>
2256
2302
  <button id="start" disabled>Start Installation</button>
2257
2303
  </div>
2258
2304
  <div class="card" id="statusCard">
@@ -2361,6 +2407,7 @@ function wizardHtml(defaults) {
2361
2407
  let llmLoadStartedAt = 0;
2362
2408
  let announcedTailscaleUrl = "";
2363
2409
  let announcedFunnelAdminUrl = "";
2410
+ let lastReferralFailFingerprint = "";
2364
2411
  let pollTimer = null;
2365
2412
  let pollIntervalMs = 1200;
2366
2413
  let installLocked = false;
@@ -2555,6 +2602,7 @@ function wizardHtml(defaults) {
2555
2602
  llmCredential: llmCredentialEl.value.trim(),
2556
2603
  apiKey: document.getElementById("apiKey").value.trim(),
2557
2604
  telegramToken: document.getElementById("telegramToken").value.trim(),
2605
+ referralCode: document.getElementById("referralCode").value.trim(),
2558
2606
  xConsumerKey: xConsumerKeyEl.value.trim(),
2559
2607
  xConsumerSecret: xConsumerSecretEl.value.trim(),
2560
2608
  xAccessTokenMain: xAccessTokenMainEl.value.trim(),
@@ -2716,9 +2764,30 @@ function wizardHtml(defaults) {
2716
2764
  }
2717
2765
 
2718
2766
  const errors = data.errors || [];
2719
- manualEl.textContent = errors.length > 0
2767
+ let manualText = errors.length > 0
2720
2768
  ? errors.map((e) => "Step " + (e.stepId || "unknown") + ":\\n" + (e.error || "")).join("\\n\\n")
2721
2769
  : "";
2770
+ const combinedErr = errors.map((e) => e.error || "").join("\\n");
2771
+ if (
2772
+ data.status === "failed"
2773
+ && /REFERRAL_CODE_INVALID|Unknown referral code/i.test(combinedErr)
2774
+ ) {
2775
+ manualText +=
2776
+ (manualText ? "\\n\\n" : "") +
2777
+ "Referral code was rejected. Clear or fix the referral field above, then click Start Installation again.";
2778
+ const fp = combinedErr.slice(0, 240);
2779
+ if (fp && fp !== lastReferralFailFingerprint) {
2780
+ lastReferralFailFingerprint = fp;
2781
+ try {
2782
+ window.alert(
2783
+ "Referral code was not accepted. Update or clear the referral field, then click Start Installation again.",
2784
+ );
2785
+ } catch {
2786
+ /* ignore */
2787
+ }
2788
+ }
2789
+ }
2790
+ manualEl.textContent = manualText;
2722
2791
  stepsEl.innerHTML = "";
2723
2792
  steps.forEach((row) => {
2724
2793
  const tr = document.createElement("tr");
@@ -2938,6 +3007,7 @@ async function cmdInstall(args) {
2938
3007
  enableTelegram: true,
2939
3008
  telegramToken: body.telegramToken || defaults.telegramToken,
2940
3009
  autoInstallDeps: true,
3010
+ referralCode: typeof body.referralCode === "string" ? body.referralCode.trim() : "",
2941
3011
  xConsumerKey: body.xConsumerKey ?? defaults.xConsumerKey,
2942
3012
  xConsumerSecret: body.xConsumerSecret ?? defaults.xConsumerSecret,
2943
3013
  xAccessTokenMain: body.xAccessTokenMain ?? defaults.xAccessTokenMain,
@@ -2973,6 +3043,7 @@ async function cmdInstall(args) {
2973
3043
  enableTelegram: true,
2974
3044
  telegramToken: body.telegramToken || defaults.telegramToken,
2975
3045
  autoInstallDeps: true,
3046
+ referralCode: wizardOpts.referralCode,
2976
3047
  xConsumerKey: wizardOpts.xConsumerKey,
2977
3048
  xConsumerSecret: wizardOpts.xConsumerSecret,
2978
3049
  xAccessTokenMain: wizardOpts.xAccessTokenMain,
@@ -3311,6 +3382,7 @@ Setup options:
3311
3382
  --gateway-base-url, -g Gateway public HTTPS URL for orchestrator callbacks
3312
3383
  --gateway-token, -t Gateway bearer token (defaults to API key)
3313
3384
  --telegram-recipient Telegram @username or chat id (aliases: --forward-telegram-chat-id, --telegram-chat-id)
3385
+ --referral-code, -r Optional referral code for new signups (extra trial time when valid)
3314
3386
  --skip-gateway-registration Skip gateway URL registration with orchestrator
3315
3387
  --show-api-key Extra hint after signup (full key is always shown once; confirm with API_KEY_STORED)
3316
3388
  --show-wallet-private-key Reveal full wallet private key in setup output
@@ -3340,7 +3412,7 @@ Examples:
3340
3412
  traderclaw install --wizard
3341
3413
  traderclaw install --wizard --lane quick-local
3342
3414
  traderclaw gateway ensure-persistent
3343
- traderclaw setup --signup --user-id my_agent_001
3415
+ traderclaw setup --signup --user-id my_agent_001 --referral-code ABCD1234
3344
3416
  traderclaw setup --api-key oc_xxx --url https://api.traderclaw.ai
3345
3417
  traderclaw setup --gateway-base-url https://gateway.myhost.ts.net
3346
3418
  traderclaw setup --telegram-recipient @myusername
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "traderclaw-cli",
3
- "version": "1.0.62",
3
+ "version": "1.0.63",
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.62"
20
+ "solana-traderclaw": "^1.0.63"
21
21
  },
22
22
  "keywords": [
23
23
  "traderclaw",