@xaidenlabs/uso 1.1.69 → 1.1.71

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xaidenlabs/uso",
3
- "version": "1.1.69",
3
+ "version": "1.1.71",
4
4
  "description": "Universal Solana Development Toolchain. Native or Stealth WSL Mode. Build, test, and deploy without the friction.",
5
5
  "bin": {
6
6
  "uso": "bin/index.js"
@@ -0,0 +1,32 @@
1
+ const shell = require('shelljs');
2
+ const os = require('os');
3
+ const { log } = require('../utils/logger');
4
+ const { isStealthMode } = require('../utils/stealth');
5
+ const { runWsl } = require('../utils/wsl-bridge');
6
+
7
+ const address = async () => {
8
+ const stealth = isStealthMode();
9
+
10
+ try {
11
+ let result;
12
+
13
+ if (stealth.enabled) {
14
+ // Run solana address inside WSL
15
+ result = runWsl('solana address', { distro: stealth.distro });
16
+ } else {
17
+ // Run solana address natively
18
+ result = shell.exec('solana address', { silent: true });
19
+ }
20
+
21
+ if (result.code === 0) {
22
+ log.success(result.stdout.trim());
23
+ } else {
24
+ const errorMsg = result.stderr || result.stdout;
25
+ log.error(errorMsg.trim());
26
+ }
27
+ } catch (e) {
28
+ log.error(`Error getting wallet address: ${e.message}`);
29
+ }
30
+ };
31
+
32
+ module.exports = { address };
@@ -1,241 +1,250 @@
1
- const os = require('os');
2
- const shell = require('shelljs');
3
- const { log, spinner } = require('../utils/logger');
4
- const { installWindows } = require('../platforms/windows');
5
- const { installMacOS } = require('../platforms/macos');
6
- const { installLinux } = require('../platforms/linux');
7
- const { getCargoBinPath } = require('../utils/paths');
8
- const { checkRust, checkSolana, checkAnchor } = require('./doctor');
9
- const { ensureWalletInteractive } = require('../utils/wallet');
10
- const path = require('path');
11
- const fs = require('fs');
12
-
13
- const { installWsl, installWslFeature } = require('../platforms/wsl');
1
+ const os = require("os");
2
+ const shell = require("shelljs");
3
+ const { log, spinner } = require("../utils/logger");
4
+ const { installWindows } = require("../platforms/windows");
5
+ const { installMacOS } = require("../platforms/macos");
6
+ const { installLinux } = require("../platforms/linux");
7
+ const { getCargoBinPath } = require("../utils/paths");
8
+ const { checkRust, checkSolana, checkAnchor } = require("./doctor");
9
+ const { ensureWalletInteractive } = require("../utils/wallet");
10
+ const path = require("path");
11
+ const fs = require("fs");
12
+
13
+ const { installWsl, installWslFeature } = require("../platforms/wsl");
14
14
 
15
15
  const init = async (component, options) => {
16
- const platform = os.platform();
16
+ const platform = os.platform();
17
17
 
18
- // --- On Windows, ALWAYS use the WSL path ---
19
- if (platform === 'win32') {
20
- const hasWslBinary = !!shell.which('wsl');
18
+ // --- On Windows, ALWAYS use the WSL path ---
19
+ if (platform === "win32") {
20
+ const hasWslBinary = !!shell.which("wsl");
21
21
 
22
- if (!hasWslBinary) {
23
- // WSL is not installed at all — request admin elevation to enable the feature
24
- log.header("🐧 Windows Subsystem for Linux (WSL) not found.");
25
- log.info("🛡️ Requesting administrator permission to install WSL...");
26
- log.info("👉 Please click 'Yes' in the UAC popup that appears to allow this.");
27
- console.log("");
22
+ if (!hasWslBinary) {
23
+ // WSL is not installed at all — request admin elevation to enable the feature
24
+ log.header("🐧 Windows Subsystem for Linux (WSL) not found.");
25
+ log.info("🛡️ Requesting administrator permission to install WSL...");
26
+ log.info(
27
+ "👉 Please click 'Yes' in the UAC popup that appears to allow this.",
28
+ );
29
+ console.log("");
28
30
 
29
- const wslInstalled = await installWslFeature();
31
+ const wslInstalled = await installWslFeature();
30
32
 
31
- if (!wslInstalled && !shell.which('wsl')) {
32
- // installWslFeature already printed the relevant error/reboot message
33
- return;
34
- }
35
-
36
- // If wsl.exe is now available, continue straight into the Ubuntu setup.
37
- // On some machines this still needs a reboot, but we let the distro phase
38
- // run immediately so setup can continue as far as the system allows.
39
- }
40
-
41
- // WSL binary is present — run the full WSL toolchain install
42
- await installWsl();
33
+ if (!wslInstalled && !shell.which("wsl")) {
34
+ // installWslFeature already printed the relevant error/reboot message
43
35
  return;
44
- }
45
-
46
- if (component) {
47
- component = component.toLowerCase();
48
- log.info(`🎯 Targeted installation: ${component}`);
49
-
50
- if (component === 'rust') {
51
- if (checkRust(true)) {
52
- log.success("✅ Rust is already installed.");
53
- return;
54
- }
55
- log.info("🦀 Installing Rust...");
56
- let success = false;
57
- if (platform === 'win32') success = await installWindows(true, false);
58
- else if (platform === 'darwin') success = await installMacOS(true, false);
59
- else success = await installLinux(true, false);
60
-
61
- if (success) log.success("✅ Rust installed successfully.");
62
- else log.error("❌ Rust installation failed.");
63
- return;
64
- }
65
-
66
- if (component === 'solana') {
67
- if (checkSolana(true)) {
68
- log.success("✅ Solana CLI is already installed.");
69
- return;
70
- }
71
- log.info("☀️ Installing Solana CLI...");
72
- let success = false;
73
- if (platform === 'win32') success = await installWindows(false, true);
74
- else if (platform === 'darwin') success = await installMacOS(false, true);
75
- else success = await installLinux(false, true);
76
-
77
- if (success) log.success("✅ Solana CLI installed successfully.");
78
- else log.error("❌ Solana CLI installation failed.");
79
- return;
80
- }
36
+ }
81
37
 
82
- if (component === 'anchor') {
83
- if (checkAnchor(true)) {
84
- log.success("✅ Anchor is already installed.");
85
- return;
86
- }
87
- // Fall through to Anchor installation logic below, but skip others
88
- } else if (component !== 'anchor') { // If it's not rust, solana, or anchor
89
- log.error(`❌ Unknown component: ${component}. Available: rust, solana, anchor`);
90
- return;
91
- }
38
+ // If wsl.exe is now available, continue straight into the Ubuntu setup.
39
+ // On some machines this still needs a reboot, but we let the distro phase
40
+ // run immediately so setup can continue as far as the system allows.
92
41
  }
93
42
 
94
- // --- FULL INSTALLATION / ANCHOR ONLY FLOW ---
43
+ // WSL binary is present run the full WSL toolchain install
44
+ await installWsl();
45
+ return;
46
+ }
95
47
 
96
- // If authenticating for just Anchor, we assume Rust/Solana are prerequisites or we skip them
97
- let installRust = !checkRust(true);
98
- let installSolana = !checkSolana(true);
99
- const hasAnchor = checkAnchor(true);
48
+ if (component) {
49
+ component = component.toLowerCase();
50
+ log.info(`🎯 Targeted installation: ${component}`);
100
51
 
101
- if (component === 'anchor') {
102
- // ensuring prerequisites for anchor
103
- if (installRust) {
104
- log.warn("⚠️ Rust is required for Anchor but not installed.");
105
- // asking or just failing? For granular, let's just fail or warn.
106
- // But let's proceed to install Anchor logic which handles cargo check
107
- }
108
- installRust = false; // Don't run platform installers for these
109
- installSolana = false;
52
+ if (component === "rust") {
53
+ if (checkRust(true)) {
54
+ log.success("✅ Rust is already installed.");
55
+ return;
56
+ }
57
+ log.info("🦀 Installing Rust...");
58
+ let success = false;
59
+ if (platform === "win32") success = await installWindows(true, false);
60
+ else if (platform === "darwin") success = await installMacOS(true, false);
61
+ else success = await installLinux(true, false);
62
+
63
+ if (success) log.success("✅ Rust installed successfully.");
64
+ else log.error("❌ Rust installation failed.");
65
+ return;
110
66
  }
111
67
 
112
- // Validating state for full install
113
- if (!component && !installRust && !installSolana && hasAnchor) {
114
- log.success("🎉 Everything is already installed!");
115
- await ensureWalletInteractive();
68
+ if (component === "solana") {
69
+ if (checkSolana(true)) {
70
+ log.success(" Solana CLI is already installed.");
116
71
  return;
72
+ }
73
+ log.info("☀️ Installing Solana CLI...");
74
+ let success = false;
75
+ if (platform === "win32") success = await installWindows(false, true);
76
+ else if (platform === "darwin") success = await installMacOS(false, true);
77
+ else success = await installLinux(false, true);
78
+
79
+ if (success) log.success("✅ Solana CLI installed successfully.");
80
+ else log.error("❌ Solana CLI installation failed.");
81
+ return;
117
82
  }
118
83
 
119
- if (!component) {
120
- log.header("🔍 Checking current environment state...");
121
- log.info(`\n📦 Missing components:`);
122
- if (installRust) log.error(" - Rust");
123
- if (installSolana) log.error(" - Solana CLI");
124
- if (!hasAnchor) log.error(" - Anchor");
125
- console.log("");
126
-
127
- const spin = spinner('Starting Installation...').start();
128
-
129
- try {
130
- let success = false;
131
-
132
- if (platform === 'win32') {
133
- spin.stop();
134
- success = await installWindows(installRust, installSolana);
135
- } else if (platform === 'darwin') {
136
- spin.stop();
137
- success = await installMacOS(installRust, installSolana);
138
- } else {
139
- spin.stop();
140
- success = await installLinux(installRust, installSolana);
141
- }
142
-
143
- if (!success) {
144
- log.error("❌ Platform-specific installation failed.");
145
- return;
146
- }
147
- } catch (e) {
148
- spin.stop();
149
- log.error(e.message);
150
- return;
151
- }
84
+ if (component === "anchor") {
85
+ if (checkAnchor(true)) {
86
+ log.success("✅ Anchor is already installed.");
87
+ return;
88
+ }
89
+ // Fall through to Anchor installation logic below, but skip others
90
+ } else if (component !== "anchor") {
91
+ // If it's not rust, solana, or anchor
92
+ log.error(
93
+ `❌ Unknown component: ${component}. Available: rust, solana, anchor`,
94
+ );
95
+ return;
152
96
  }
97
+ }
153
98
 
154
- // Install Anchor (Universal) - Runs if component='anchor' OR full install
155
- if (!hasAnchor && (!component || component === 'anchor')) {
156
- log.info("⚓ Installing Anchor Framework...");
99
+ // --- FULL INSTALLATION / ANCHOR ONLY FLOW ---
157
100
 
158
- const cargoBin = getCargoBinPath();
159
- const cargoExe = platform === 'win32' ? 'cargo.exe' : 'cargo';
160
- const avmExe = platform === 'win32' ? 'avm.exe' : 'avm';
101
+ // If authenticating for just Anchor, we assume Rust/Solana are prerequisites or we skip them
102
+ let installRust = !checkRust(true);
103
+ let installSolana = !checkSolana(true);
104
+ const hasAnchor = checkAnchor(true);
161
105
 
162
- // Resolve cargo command
163
- let cargoCmd = cargoExe;
164
- if (fs.existsSync(path.join(cargoBin, cargoExe))) {
165
- cargoCmd = `"${path.join(cargoBin, cargoExe)}"`;
166
- } else if (!installRust && checkRust(true)) {
167
- cargoCmd = 'cargo';
168
- }
106
+ if (component === "anchor") {
107
+ // ensuring prerequisites for anchor
108
+ if (installRust) {
109
+ log.warn("⚠️ Rust is required for Anchor but not installed.");
110
+ // asking or just failing? For granular, let's just fail or warn.
111
+ // But let's proceed to install Anchor logic which handles cargo check
112
+ }
113
+ installRust = false; // Don't run platform installers for these
114
+ installSolana = false;
115
+ }
116
+
117
+ // Validating state for full install
118
+ if (!component && !installRust && !installSolana && hasAnchor) {
119
+ log.success("🎉 Everything is already installed!");
120
+ await ensureWalletInteractive();
121
+ return;
122
+ }
123
+
124
+ if (!component) {
125
+ log.header("🔍 Checking current environment state...");
126
+ log.info(`\n📦 Missing components:`);
127
+ if (installRust) log.error(" - Rust");
128
+ if (installSolana) log.error(" - Solana CLI");
129
+ if (!hasAnchor) log.error(" - Anchor");
130
+ console.log("");
131
+
132
+ const spin = spinner("Starting Installation...").start();
133
+
134
+ try {
135
+ let success = false;
136
+
137
+ if (platform === "win32") {
138
+ spin.stop();
139
+ success = await installWindows(installRust, installSolana);
140
+ } else if (platform === "darwin") {
141
+ spin.stop();
142
+ success = await installMacOS(installRust, installSolana);
143
+ } else {
144
+ spin.stop();
145
+ success = await installLinux(installRust, installSolana);
146
+ }
147
+
148
+ if (!success) {
149
+ log.error("❌ Platform-specific installation failed.");
150
+ return;
151
+ }
152
+ } catch (e) {
153
+ spin.stop();
154
+ log.error(e.message);
155
+ return;
156
+ }
157
+ }
158
+
159
+ // Install Anchor (Universal) - Runs if component='anchor' OR full install
160
+ if (!hasAnchor && (!component || component === "anchor")) {
161
+ log.info("⚓ Installing Anchor Framework...");
162
+
163
+ const cargoBin = getCargoBinPath();
164
+ const cargoExe = platform === "win32" ? "cargo.exe" : "cargo";
165
+ const avmExe = platform === "win32" ? "avm.exe" : "avm";
166
+
167
+ // Resolve cargo command
168
+ let cargoCmd = cargoExe;
169
+ if (fs.existsSync(path.join(cargoBin, cargoExe))) {
170
+ cargoCmd = `"${path.join(cargoBin, cargoExe)}"`;
171
+ } else if (!installRust && checkRust(true)) {
172
+ cargoCmd = "cargo";
173
+ }
169
174
 
170
- log.subHeader(`Using cargo: ${cargoCmd}`);
171
-
172
- // Try installing AVM first (Preferred)
173
- log.info(" Attempting AVM install...");
174
- const avmInstall = shell.exec(`${cargoCmd} install --git https://github.com/coral-xyz/anchor avm --locked --force`);
175
-
176
- if (avmInstall.code === 0) {
177
- // Use AVM
178
- let avmCmd = avmExe;
179
- if (fs.existsSync(path.join(cargoBin, avmExe))) {
180
- avmCmd = `"${path.join(cargoBin, avmExe)}"`;
181
- }
182
-
183
- log.subHeader(`Using avm: ${avmCmd}`);
184
- const avmUse = shell.exec(`${avmCmd} install latest`);
185
-
186
- // Detect Permission Error for AVM
187
- if (avmUse.code !== 0) {
188
- const output = avmUse.stderr + avmUse.stdout;
189
- if (output.includes("os error 1314") && platform === 'win32') {
190
- log.warn("⚠️ AVM Permission denied (Symlink creation failed).");
191
- log.info("🛡️ Triggering Run as Administrator (UAC) for Anchor...");
192
- const absAvmPath = path.join(cargoBin, avmExe);
193
- const elevateCmd = `powershell -Command "Start-Process -FilePath '${absAvmPath}' -ArgumentList 'install latest' -Verb RunAs -Wait; Start-Process -FilePath '${absAvmPath}' -ArgumentList 'use latest' -Verb RunAs -Wait"`;
194
- const elevatedRun = shell.exec(elevateCmd);
195
-
196
- if (elevatedRun.code === 0) {
197
- log.success("✅ Anchor installed (Elevated).");
198
- } else {
199
- log.error(" Elevated installation failed. Trying fallback...");
200
- fallbackDirectInstall(cargoCmd);
201
- }
202
-
203
- } else {
204
- log.warn("⚠️ AVM installation failed. Trying fallback...");
205
- fallbackDirectInstall(cargoCmd);
206
- }
207
- } else {
208
- shell.exec(`${avmCmd} use latest`);
209
- log.success("✅ Anchor installed.");
210
- }
175
+ log.subHeader(`Using cargo: ${cargoCmd}`);
176
+
177
+ // Try installing AVM first (Preferred)
178
+ log.info(" Attempting AVM install...");
179
+ const avmInstall = shell.exec(
180
+ `${cargoCmd} install --git https://github.com/coral-xyz/anchor avm --locked --force`,
181
+ );
182
+
183
+ if (avmInstall.code === 0) {
184
+ // Use AVM
185
+ let avmCmd = avmExe;
186
+ if (fs.existsSync(path.join(cargoBin, avmExe))) {
187
+ avmCmd = `"${path.join(cargoBin, avmExe)}"`;
188
+ }
189
+
190
+ log.subHeader(`Using avm: ${avmCmd}`);
191
+ const avmUse = shell.exec(`${avmCmd} install latest`);
192
+
193
+ // Detect Permission Error for AVM
194
+ if (avmUse.code !== 0) {
195
+ const output = avmUse.stderr + avmUse.stdout;
196
+ if (output.includes("os error 1314") && platform === "win32") {
197
+ log.warn("⚠️ AVM Permission denied (Symlink creation failed).");
198
+ log.info("🛡️ Triggering Run as Administrator (UAC) for Anchor...");
199
+ const absAvmPath = path.join(cargoBin, avmExe);
200
+ const elevateCmd = `powershell -Command "Start-Process -FilePath '${absAvmPath}' -ArgumentList 'install latest' -Verb RunAs -Wait; Start-Process -FilePath '${absAvmPath}' -ArgumentList 'use latest' -Verb RunAs -Wait"`;
201
+ const elevatedRun = shell.exec(elevateCmd);
202
+
203
+ if (elevatedRun.code === 0) {
204
+ log.success(" Anchor installed (Elevated).");
205
+ } else {
206
+ log.error("❌ Elevated installation failed. Trying fallback...");
207
+ fallbackDirectInstall(cargoCmd);
208
+ }
211
209
  } else {
212
- log.error(" Failed to install AVM via Cargo.");
213
- return;
210
+ log.warn("⚠️ AVM installation failed. Trying fallback...");
211
+ fallbackDirectInstall(cargoCmd);
214
212
  }
215
- } else if (component === 'anchor' && hasAnchor) {
216
- log.success("✅ Anchor is already installed.");
213
+ } else {
214
+ shell.exec(`${avmCmd} use latest`);
215
+ log.success("✅ Anchor installed.");
216
+ }
217
+ } else {
218
+ log.error("❌ Failed to install AVM via Cargo.");
219
+ return;
217
220
  }
218
-
219
-
220
- if (!component) {
221
- log.header('\n✅ Uso Setup Complete!');
222
- await ensureWalletInteractive();
223
-
224
- if (installRust || installSolana || !hasAnchor) {
225
- log.warn('👉 Please RESTART your terminal/VS Code to ensure all PATH variables are updated.');
226
- }
227
- log.info('🚀 Try running: uso verify');
221
+ } else if (component === "anchor" && hasAnchor) {
222
+ log.success("✅ Anchor is already installed.");
223
+ }
224
+
225
+ if (!component) {
226
+ log.header("\n✅ Uso Setup Complete!");
227
+ await ensureWalletInteractive();
228
+
229
+ if (installRust || installSolana || !hasAnchor) {
230
+ log.warn(
231
+ "👉 Please RESTART your terminal/VS Code to ensure all PATH variables are updated.",
232
+ );
228
233
  }
234
+ log.info("🚀 Try running: uso verify");
235
+ }
229
236
  };
230
237
 
231
238
  const fallbackDirectInstall = (cargoCmd) => {
232
- log.info("👉 Falling back to direct 'anchor-cli' installation...");
233
- const directInstall = shell.exec(`${cargoCmd} install --git https://github.com/coral-xyz/anchor anchor-cli --locked --force`);
234
- if (directInstall.code !== 0) {
235
- log.error("❌ Failed to install Anchor via fallback method.");
236
- } else {
237
- log.success(" Anchor installed (Direct Cargo).");
238
- }
239
+ log.info("👉 Falling back to direct 'anchor-cli' installation...");
240
+ const directInstall = shell.exec(
241
+ `${cargoCmd} install --git https://github.com/coral-xyz/anchor anchor-cli --locked --force`,
242
+ );
243
+ if (directInstall.code !== 0) {
244
+ log.error(" Failed to install Anchor via fallback method.");
245
+ } else {
246
+ log.success("✅ Anchor installed (Direct Cargo).");
247
+ }
239
248
  };
240
249
 
241
250
  module.exports = { init };
@@ -331,6 +331,33 @@ const uninstall = async (component) => {
331
331
  }
332
332
  }
333
333
 
334
+ // 3.5 Remove WSL Distro (if stealth mode is active)
335
+ if (stealth.enabled && os.platform() === "win32") {
336
+ const removeWslDistro = await askQuestion(
337
+ "\n🐧 Remove WSL Ubuntu distro completely? (y/N): ",
338
+ );
339
+ if (removeWslDistro.toLowerCase() === "y") {
340
+ log.warn(`⚠️ This will completely remove the ${stealth.distro} distro and all its data.`);
341
+ const confirmWslRemoval = await askQuestion(
342
+ "💥 Type 'REMOVE WSL' to confirm distro removal: ",
343
+ );
344
+ if (confirmWslRemoval === "REMOVE WSL") {
345
+ log.info(`Unregistering ${stealth.distro} distro...`);
346
+ const unregisterCmd = `wsl --unregister ${stealth.distro}`;
347
+ const result = runOrElevate(
348
+ unregisterCmd,
349
+ `Unregister WSL distro ${stealth.distro}`,
350
+ { enabled: false, distro: stealth.distro },
351
+ );
352
+ if (result) {
353
+ log.success(`✅ ${stealth.distro} distro removed.`);
354
+ }
355
+ } else {
356
+ log.info("WSL distro removal cancelled.");
357
+ }
358
+ }
359
+ }
360
+
334
361
  // 4. WALLET REMOVAL (DANGER)
335
362
  const walletPath = path.join(os.homedir(), ".config", "solana", "id.json");
336
363
  const wslWalletPath = "$HOME/.config/solana/id.json";
@@ -281,14 +281,54 @@ source $HOME/.cargo/env 2>/dev/null || true
281
281
  export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"
282
282
  if ! command -v solana &> /dev/null; then
283
283
  echo "☀️ Installing Solana CLI..."
284
- if run_with_progress "☀️ Installing Solana CLI..." 35 60 bash -lc 'sh -c "$(curl -sSfL https://release.solana.com/stable/install)"'; then
284
+
285
+ # Helper to download with retries and proper SSL handling
286
+ install_solana_with_retry() {
287
+ local url="$1"
288
+ local description="$2"
289
+ local max_attempts=3
290
+ local attempt=1
291
+
292
+ while [ $attempt -le $max_attempts ]; do
293
+ if [ $attempt -gt 1 ]; then
294
+ echo " Retry attempt $attempt/$max_attempts..."
295
+ sleep 2
296
+ fi
297
+
298
+ # Download installer script with SSL options and timeout
299
+ if curl --proto '=https' --tlsv1.2 -sSf --max-time 60 --connect-timeout 10 \
300
+ --cacert /etc/ssl/certs/ca-certificates.crt \
301
+ "$url" > /tmp/solana_install.sh 2>/dev/null; then
302
+ # Execute the downloaded script
303
+ if bash /tmp/solana_install.sh; then
304
+ rm -f /tmp/solana_install.sh
305
+ return 0
306
+ fi
307
+ fi
308
+
309
+ attempt=$((attempt + 1))
310
+ done
311
+
312
+ rm -f /tmp/solana_install.sh
313
+ return 1
314
+ }
315
+
316
+ solana_installed=0
317
+
318
+ # Try official Solana release
319
+ if install_solana_with_retry "https://release.solana.com/stable/install" "Solana"; then
320
+ solana_installed=1
285
321
  echo "✅ Solana installed."
286
- elif run_with_progress "☀️ Installing Solana CLI..." 35 60 bash -lc 'sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"'; then
322
+ # Fallback to Agave (community-maintained)
323
+ elif install_solana_with_retry "https://release.anza.xyz/stable/install" "Agave"; then
324
+ solana_installed=1
287
325
  echo "✅ Solana installed (via Agave)."
288
326
  else
289
327
  FAILURES="$FAILURES solana"
290
- echo "⚠️ Solana install timed out. Run 'uso setup' again later to retry."
328
+ echo "⚠️ Solana install failed after retries. Network or certificate issue detected."
329
+ echo " Run 'uso init' again to retry."
291
330
  fi
331
+
292
332
  export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"
293
333
  else
294
334
  echo "✅ Solana already installed."
@@ -4,6 +4,8 @@ const path = require('path');
4
4
  const fs = require('fs');
5
5
  const readline = require('readline');
6
6
  const { log } = require('./logger');
7
+ const { isStealthMode } = require('./stealth');
8
+ const { runWsl } = require('./wsl-bridge');
7
9
 
8
10
  const resolveSolanaKeygen = () => {
9
11
  // 1. Try PATH first
@@ -25,12 +27,31 @@ const resolveSolanaKeygen = () => {
25
27
  * Returns true if wallet exists (or was created), false if user declined.
26
28
  */
27
29
  const ensureWalletInteractive = async () => {
28
- const walletDir = path.join(os.homedir(), '.config', 'solana');
29
- const walletPath = path.join(walletDir, 'id.json');
30
+ const stealth = isStealthMode();
31
+
32
+ // When in stealth mode, wallet is in WSL home
33
+ let walletDir, walletPath;
34
+ if (stealth.enabled) {
35
+ walletDir = '$HOME/.config/solana';
36
+ walletPath = '$HOME/.config/solana/id.json';
37
+ } else {
38
+ walletDir = path.join(os.homedir(), '.config', 'solana');
39
+ walletPath = path.join(walletDir, 'id.json');
40
+ }
30
41
 
31
- if (fs.existsSync(walletPath)) {
32
- log.info("🔑 Wallet found.");
33
- return true;
42
+ // Check if wallet exists
43
+ if (stealth.enabled) {
44
+ // Check inside WSL
45
+ const checkWallet = runWsl('test -f $HOME/.config/solana/id.json && echo "exists"', { distro: stealth.distro });
46
+ if (checkWallet.code === 0 && checkWallet.stdout.includes('exists')) {
47
+ log.info("🔑 Wallet found (in WSL).");
48
+ return true;
49
+ }
50
+ } else {
51
+ if (fs.existsSync(walletPath)) {
52
+ log.info("🔑 Wallet found.");
53
+ return true;
54
+ }
34
55
  }
35
56
 
36
57
  const rl = readline.createInterface({
@@ -45,28 +66,51 @@ const ensureWalletInteractive = async () => {
45
66
  rl.close();
46
67
  if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
47
68
  log.info("🔑 Generating wallet...");
48
- if (!fs.existsSync(walletDir)) fs.mkdirSync(walletDir, { recursive: true });
69
+
70
+ try {
71
+ if (stealth.enabled) {
72
+ // Create wallet inside WSL
73
+ const mkdirCmd = 'mkdir -p $HOME/.config/solana';
74
+ runWsl(mkdirCmd, { distro: stealth.distro });
75
+
76
+ // Run solana-keygen inside WSL with interactive mode
77
+ const { spawnSync } = require('child_process');
78
+ const wslCmd = `wsl -d ${stealth.distro} -e bash -c "solana-keygen new --outfile \\$HOME/.config/solana/id.json"`;
79
+ spawnSync('cmd.exe', ['/c', wslCmd], { stdio: 'inherit' });
80
+
81
+ // Verify wallet was created in WSL
82
+ const verifyCmd = runWsl('test -f $HOME/.config/solana/id.json && echo "exists"', { distro: stealth.distro });
83
+ if (verifyCmd.code === 0 && verifyCmd.stdout.includes('exists')) {
84
+ log.success("✅ Wallet generated (in WSL).");
85
+ resolve(true);
86
+ } else {
87
+ log.warn("❌ Creation cancelled or failed.");
88
+ resolve(false);
89
+ }
90
+ } else {
91
+ // Create wallet natively on Windows
92
+ if (!fs.existsSync(walletDir)) fs.mkdirSync(walletDir, { recursive: true });
49
93
 
50
- const keygenCmd = resolveSolanaKeygen();
94
+ const keygenCmd = resolveSolanaKeygen();
51
95
 
52
- // Use spawnSync to allow interactive input (passphrase)
53
- const { spawnSync } = require('child_process');
96
+ // Use spawnSync to allow interactive input (passphrase)
97
+ const { spawnSync } = require('child_process');
54
98
 
55
- // We need to strip quotes for spawn
56
- let cmd = keygenCmd;
57
- if (cmd.startsWith('"') && cmd.endsWith('"')) cmd = cmd.slice(1, -1);
99
+ // We need to strip quotes for spawn
100
+ let cmd = keygenCmd;
101
+ if (cmd.startsWith('"') && cmd.endsWith('"')) cmd = cmd.slice(1, -1);
58
102
 
59
- try {
60
- // We use 'new' command which might prompt for passphrase
61
- spawnSync(cmd, ['new', '--outfile', walletPath], { stdio: 'inherit', shell: true });
103
+ // We use 'new' command which might prompt for passphrase
104
+ spawnSync(cmd, ['new', '--outfile', walletPath], { stdio: 'inherit', shell: true });
62
105
 
63
- if (fs.existsSync(walletPath)) {
64
- log.success("✅ Wallet generated.");
65
- resolve(true);
66
- } else {
67
- // User might have cancelled via Ctrl+C in the subprocess
68
- log.warn("❌ Creation cancelled or failed.");
69
- resolve(false);
106
+ if (fs.existsSync(walletPath)) {
107
+ log.success("✅ Wallet generated.");
108
+ resolve(true);
109
+ } else {
110
+ // User might have cancelled via Ctrl+C in the subprocess
111
+ log.warn("❌ Creation cancelled or failed.");
112
+ resolve(false);
113
+ }
70
114
  }
71
115
  } catch (e) {
72
116
  log.error("❌ Failed to generate wallet: " + e.message);