blue-js-sdk 2.0.0

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.
Files changed (215) hide show
  1. package/CHANGELOG.md +446 -0
  2. package/LICENSE +21 -0
  3. package/README.md +75 -0
  4. package/ai-path/ADMIN-ELEVATION.md +116 -0
  5. package/ai-path/AI-MANIFESTO.md +185 -0
  6. package/ai-path/BREAKING.md +74 -0
  7. package/ai-path/CHECKLIST.md +619 -0
  8. package/ai-path/CONNECTION-STEPS.md +724 -0
  9. package/ai-path/DECISION-TREE.md +378 -0
  10. package/ai-path/DEPENDENCIES.md +459 -0
  11. package/ai-path/E2E-FLOW.md +1555 -0
  12. package/ai-path/FAILURES.md +403 -0
  13. package/ai-path/GUIDE.md +1217 -0
  14. package/ai-path/README.md +558 -0
  15. package/ai-path/SPLIT-TUNNEL.md +266 -0
  16. package/ai-path/cli.js +535 -0
  17. package/ai-path/connect.js +884 -0
  18. package/ai-path/discover.js +178 -0
  19. package/ai-path/environment.js +266 -0
  20. package/ai-path/errors.js +86 -0
  21. package/ai-path/examples/autonomous-agent.mjs +220 -0
  22. package/ai-path/examples/multi-region.mjs +174 -0
  23. package/ai-path/examples/one-shot.mjs +31 -0
  24. package/ai-path/index.js +60 -0
  25. package/ai-path/pricing.js +136 -0
  26. package/ai-path/recommend.js +413 -0
  27. package/ai-path/run-admin.vbs +25 -0
  28. package/ai-path/setup.js +291 -0
  29. package/ai-path/wallet.js +137 -0
  30. package/app-helpers.js +363 -0
  31. package/app-settings.js +95 -0
  32. package/app-types.js +267 -0
  33. package/audit.js +847 -0
  34. package/batch.js +293 -0
  35. package/bin/setup.js +376 -0
  36. package/chain/authz.js +109 -0
  37. package/chain/broadcast.js +472 -0
  38. package/chain/client.js +160 -0
  39. package/chain/fee-grants.js +305 -0
  40. package/chain/index.js +891 -0
  41. package/chain/lcd.js +313 -0
  42. package/chain/queries.js +547 -0
  43. package/chain/rpc.js +408 -0
  44. package/chain/wallet.js +141 -0
  45. package/cli/config.js +143 -0
  46. package/cli/index.js +463 -0
  47. package/cli/output.js +182 -0
  48. package/cli.js +491 -0
  49. package/client/index.js +251 -0
  50. package/client.js +271 -0
  51. package/config/index.js +255 -0
  52. package/connection/connect.js +849 -0
  53. package/connection/disconnect.js +180 -0
  54. package/connection/discovery.js +321 -0
  55. package/connection/index.js +76 -0
  56. package/connection/proxy.js +148 -0
  57. package/connection/resilience.js +428 -0
  58. package/connection/security.js +232 -0
  59. package/connection/state.js +369 -0
  60. package/connection/tunnel.js +691 -0
  61. package/consumer.js +132 -0
  62. package/cosmjs-setup.js +1884 -0
  63. package/defaults.js +366 -0
  64. package/disk-cache.js +107 -0
  65. package/dist/client.d.ts +108 -0
  66. package/dist/client.d.ts.map +1 -0
  67. package/dist/client.js +400 -0
  68. package/dist/client.js.map +1 -0
  69. package/dist/index.d.ts +8 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/dist/index.js +8 -0
  72. package/dist/index.js.map +1 -0
  73. package/errors/index.js +112 -0
  74. package/errors.js +218 -0
  75. package/examples/README.md +64 -0
  76. package/examples/connect-direct.mjs +106 -0
  77. package/examples/connect-plan.mjs +125 -0
  78. package/examples/error-handling.mjs +109 -0
  79. package/examples/query-nodes.mjs +94 -0
  80. package/examples/wallet-basics.mjs +61 -0
  81. package/generated/amino/amino.ts +9 -0
  82. package/generated/cosmos/base/v1beta1/coin.ts +365 -0
  83. package/generated/cosmos_proto/cosmos.ts +323 -0
  84. package/generated/gogoproto/gogo.ts +9 -0
  85. package/generated/google/protobuf/descriptor.ts +7601 -0
  86. package/generated/google/protobuf/duration.ts +208 -0
  87. package/generated/google/protobuf/timestamp.ts +238 -0
  88. package/generated/sentinel/lease/v1/events.ts +924 -0
  89. package/generated/sentinel/lease/v1/lease.ts +292 -0
  90. package/generated/sentinel/lease/v1/msg.ts +949 -0
  91. package/generated/sentinel/lease/v1/params.ts +164 -0
  92. package/generated/sentinel/node/v3/events.ts +881 -0
  93. package/generated/sentinel/node/v3/msg.ts +1002 -0
  94. package/generated/sentinel/node/v3/node.ts +263 -0
  95. package/generated/sentinel/node/v3/params.ts +183 -0
  96. package/generated/sentinel/plan/v3/events.ts +675 -0
  97. package/generated/sentinel/plan/v3/msg.ts +1191 -0
  98. package/generated/sentinel/plan/v3/plan.ts +283 -0
  99. package/generated/sentinel/provider/v2/events.ts +171 -0
  100. package/generated/sentinel/provider/v2/msg.ts +480 -0
  101. package/generated/sentinel/provider/v2/params.ts +131 -0
  102. package/generated/sentinel/provider/v2/provider.ts +246 -0
  103. package/generated/sentinel/session/v3/events.ts +480 -0
  104. package/generated/sentinel/session/v3/msg.ts +616 -0
  105. package/generated/sentinel/session/v3/params.ts +260 -0
  106. package/generated/sentinel/session/v3/proof.ts +180 -0
  107. package/generated/sentinel/session/v3/session.ts +384 -0
  108. package/generated/sentinel/subscription/v3/events.ts +1181 -0
  109. package/generated/sentinel/subscription/v3/msg.ts +1305 -0
  110. package/generated/sentinel/subscription/v3/params.ts +167 -0
  111. package/generated/sentinel/subscription/v3/subscription.ts +315 -0
  112. package/generated/sentinel/types/v1/bandwidth.ts +124 -0
  113. package/generated/sentinel/types/v1/price.ts +149 -0
  114. package/generated/sentinel/types/v1/renewal.ts +87 -0
  115. package/generated/sentinel/types/v1/status.ts +54 -0
  116. package/generated/typeRegistry.ts +27 -0
  117. package/index.js +486 -0
  118. package/node-connect.js +3015 -0
  119. package/operator.js +134 -0
  120. package/package.json +113 -0
  121. package/plan-operations.js +199 -0
  122. package/preflight.js +352 -0
  123. package/pricing/index.js +262 -0
  124. package/proto/amino/amino.proto +84 -0
  125. package/proto/cosmos/base/v1beta1/coin.proto +61 -0
  126. package/proto/cosmos_proto/cosmos.proto +112 -0
  127. package/proto/gogoproto/gogo.proto +145 -0
  128. package/proto/google/api/annotations.proto +31 -0
  129. package/proto/google/api/http.proto +370 -0
  130. package/proto/google/protobuf/any.proto +106 -0
  131. package/proto/google/protobuf/duration.proto +115 -0
  132. package/proto/google/protobuf/timestamp.proto +145 -0
  133. package/proto/sentinel/lease/v1/events.proto +52 -0
  134. package/proto/sentinel/lease/v1/genesis.proto +15 -0
  135. package/proto/sentinel/lease/v1/lease.proto +25 -0
  136. package/proto/sentinel/lease/v1/msg.proto +62 -0
  137. package/proto/sentinel/lease/v1/params.proto +17 -0
  138. package/proto/sentinel/node/v3/events.proto +50 -0
  139. package/proto/sentinel/node/v3/genesis.proto +15 -0
  140. package/proto/sentinel/node/v3/msg.proto +63 -0
  141. package/proto/sentinel/node/v3/node.proto +27 -0
  142. package/proto/sentinel/node/v3/params.proto +21 -0
  143. package/proto/sentinel/node/v3/querier.proto +63 -0
  144. package/proto/sentinel/plan/v3/events.proto +41 -0
  145. package/proto/sentinel/plan/v3/genesis.proto +21 -0
  146. package/proto/sentinel/plan/v3/msg.proto +83 -0
  147. package/proto/sentinel/plan/v3/plan.proto +32 -0
  148. package/proto/sentinel/plan/v3/querier.proto +53 -0
  149. package/proto/sentinel/provider/v2/events.proto +16 -0
  150. package/proto/sentinel/provider/v2/genesis.proto +15 -0
  151. package/proto/sentinel/provider/v2/msg.proto +35 -0
  152. package/proto/sentinel/provider/v2/params.proto +17 -0
  153. package/proto/sentinel/provider/v2/provider.proto +24 -0
  154. package/proto/sentinel/provider/v3/genesis.proto +15 -0
  155. package/proto/sentinel/provider/v3/params.proto +13 -0
  156. package/proto/sentinel/session/v3/events.proto +30 -0
  157. package/proto/sentinel/session/v3/genesis.proto +15 -0
  158. package/proto/sentinel/session/v3/msg.proto +50 -0
  159. package/proto/sentinel/session/v3/params.proto +25 -0
  160. package/proto/sentinel/session/v3/proof.proto +25 -0
  161. package/proto/sentinel/session/v3/querier.proto +100 -0
  162. package/proto/sentinel/session/v3/session.proto +50 -0
  163. package/proto/sentinel/subscription/v2/allocation.proto +21 -0
  164. package/proto/sentinel/subscription/v2/payout.proto +22 -0
  165. package/proto/sentinel/subscription/v3/events.proto +65 -0
  166. package/proto/sentinel/subscription/v3/genesis.proto +17 -0
  167. package/proto/sentinel/subscription/v3/msg.proto +83 -0
  168. package/proto/sentinel/subscription/v3/params.proto +21 -0
  169. package/proto/sentinel/subscription/v3/subscription.proto +33 -0
  170. package/proto/sentinel/types/v1/bandwidth.proto +19 -0
  171. package/proto/sentinel/types/v1/price.proto +21 -0
  172. package/proto/sentinel/types/v1/renewal.proto +21 -0
  173. package/proto/sentinel/types/v1/status.proto +16 -0
  174. package/protocol/encoding.js +341 -0
  175. package/protocol/events.js +361 -0
  176. package/protocol/handshake.js +297 -0
  177. package/protocol/index.js +15 -0
  178. package/protocol/messages.js +346 -0
  179. package/protocol/plans.js +199 -0
  180. package/protocol/v2ray.js +268 -0
  181. package/protocol/v3.js +723 -0
  182. package/protocol/wireguard.js +125 -0
  183. package/security/index.js +132 -0
  184. package/session-manager.js +329 -0
  185. package/session-tracker.js +80 -0
  186. package/setup.js +376 -0
  187. package/speedtest/index.js +528 -0
  188. package/speedtest.js +567 -0
  189. package/src/client.ts +502 -0
  190. package/src/index.ts +20 -0
  191. package/state/index.js +347 -0
  192. package/state.js +516 -0
  193. package/test-all-chain-ops.js +493 -0
  194. package/test-all-logic.js +199 -0
  195. package/test-all-msg-types.js +292 -0
  196. package/test-every-connection.js +208 -0
  197. package/test-feegrant-connect.js +98 -0
  198. package/test-logic.js +148 -0
  199. package/test-mainnet.js +176 -0
  200. package/test-plan-lifecycle.js +335 -0
  201. package/tls-trust.js +132 -0
  202. package/tsconfig.build.json +20 -0
  203. package/tsconfig.json +34 -0
  204. package/types/chain.d.ts +746 -0
  205. package/types/connection.d.ts +425 -0
  206. package/types/errors.d.ts +174 -0
  207. package/types/index.d.ts +1380 -0
  208. package/types/nodes.d.ts +187 -0
  209. package/types/pricing.d.ts +156 -0
  210. package/types/protocol.d.ts +332 -0
  211. package/types/session.d.ts +236 -0
  212. package/types/settings.d.ts +192 -0
  213. package/v3protocol.js +1053 -0
  214. package/wallet/index.js +153 -0
  215. package/wireguard.js +307 -0
package/setup.js ADDED
@@ -0,0 +1,376 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Sentinel dVPN SDK — Setup Script
4
+ *
5
+ * Downloads required binaries (V2Ray, WireGuard) for the current platform.
6
+ * Run: node setup.js
7
+ *
8
+ * What it does:
9
+ * 1. Checks if V2Ray v5.2.1 exists in bin/ — downloads if missing
10
+ * 2. Checks if WireGuard is installed — prints install instructions if missing
11
+ * 3. Verifies all SDK dependencies are installed (npm install)
12
+ */
13
+
14
+ import { existsSync, mkdirSync, createWriteStream, unlinkSync, readFileSync } from 'fs';
15
+ import { execSync, execFileSync } from 'child_process';
16
+ import { createHash } from 'crypto';
17
+ import path from 'path';
18
+ import { fileURLToPath } from 'url';
19
+ import https from 'https';
20
+ import http from 'http';
21
+
22
+
23
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
24
+ const BIN_DIR = path.join(__dirname, 'bin');
25
+
26
+ import { V2RAY_VERSION } from './defaults.js';
27
+ const V2RAY_URLS = {
28
+ 'win32-x64': `https://github.com/v2fly/v2ray-core/releases/download/v${V2RAY_VERSION}/v2ray-windows-64.zip`,
29
+ 'win32-ia32': `https://github.com/v2fly/v2ray-core/releases/download/v${V2RAY_VERSION}/v2ray-windows-32.zip`,
30
+ 'linux-x64': `https://github.com/v2fly/v2ray-core/releases/download/v${V2RAY_VERSION}/v2ray-linux-64.zip`,
31
+ 'linux-arm64':`https://github.com/v2fly/v2ray-core/releases/download/v${V2RAY_VERSION}/v2ray-linux-arm64-v8a.zip`,
32
+ 'darwin-x64': `https://github.com/v2fly/v2ray-core/releases/download/v${V2RAY_VERSION}/v2ray-macos-64.zip`,
33
+ 'darwin-arm64':`https://github.com/v2fly/v2ray-core/releases/download/v${V2RAY_VERSION}/v2ray-macos-arm64-v8a.zip`,
34
+ };
35
+
36
+ const V2RAY_BINARY = process.platform === 'win32' ? 'v2ray.exe' : 'v2ray';
37
+ const V2RAY_FILES = [V2RAY_BINARY, 'geoip.dat', 'geosite.dat'];
38
+
39
+ // SHA256 checksums for V2Ray v5.2.1 release binaries (from official .dgst files)
40
+ const V2RAY_SHA256 = {
41
+ 'win32-x64': 'd9791f911b603437a34219488b0111ae9913f38abe22c0103abce330537dabd6',
42
+ 'win32-ia32': 'dc9f37dbeb32221e62b9a52b79f1842a217f049675872b334e1e5fd96121d0d2',
43
+ 'linux-x64': '56eb8d4727b058d10f8ff830bb0121381386b0695171767f38ba410f2613fc9a',
44
+ 'linux-arm64': '63958429e93f24f10f34a64701f70b4f42dfa0bc8120e1c0a426c6161bd2a3c9',
45
+ 'darwin-x64': 'edbb0b94c05570d39a4549186927369853542649eb6b703dd432bda300c5d51a',
46
+ 'darwin-arm64':'e18c17a79c4585d963395ae6ddafffb18c5d22777f7ac5938c1b40563db88d56',
47
+ };
48
+
49
+ // ─── WireGuard Download URLs (verified 2026-03-26) ─────────────────────────
50
+ // Direct MSI downloads — no browser, no bootstrapper, silent-installable
51
+ const WG_VERSION = '0.5.3';
52
+ const WG_URLS = {
53
+ 'win32-x64': `https://download.wireguard.com/windows-client/wireguard-amd64-${WG_VERSION}.msi`,
54
+ 'win32-arm64': `https://download.wireguard.com/windows-client/wireguard-arm64-${WG_VERSION}.msi`,
55
+ 'win32-ia32': `https://download.wireguard.com/windows-client/wireguard-x86-${WG_VERSION}.msi`,
56
+ };
57
+ const WG_INSTALL_URL = 'https://download.wireguard.com/windows-client/wireguard-installer.exe';
58
+
59
+ // ─── Helpers ────────────────────────────────────────────────────────────────
60
+
61
+ function log(msg) { console.log(`[setup] ${msg}`); }
62
+ function warn(msg) { console.log(`[setup] ⚠ ${msg}`); }
63
+ function ok(msg) { console.log(`[setup] ✓ ${msg}`); }
64
+
65
+ function download(url, dest) {
66
+ return new Promise((resolve, reject) => {
67
+ const follow = (url, redirects = 0) => {
68
+ if (redirects > 5) return reject(new Error('Too many redirects'));
69
+ const mod = url.startsWith('https') ? https : http;
70
+ mod.get(url, { headers: { 'User-Agent': 'sentinel-sdk-setup' } }, (res) => {
71
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
72
+ return follow(res.headers.location, redirects + 1);
73
+ }
74
+ if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode} for ${url}`));
75
+ const file = createWriteStream(dest);
76
+ res.pipe(file);
77
+ file.on('finish', () => file.close(resolve));
78
+ file.on('error', reject);
79
+ }).on('error', reject);
80
+ };
81
+ follow(url);
82
+ });
83
+ }
84
+
85
+ function unzip(zipPath, destDir) {
86
+ // Use PowerShell on Windows, unzip on others
87
+ if (process.platform === 'win32') {
88
+ execFileSync('powershell', ['-NoProfile', '-Command', `Expand-Archive -Force -Path '${zipPath}' -DestinationPath '${destDir}'`], { stdio: 'pipe' });
89
+ } else {
90
+ execFileSync('unzip', ['-o', zipPath, '-d', destDir], { stdio: 'pipe' });
91
+ }
92
+ }
93
+
94
+ // ─── V2Ray ──────────────────────────────────────────────────────────────────
95
+
96
+ async function setupV2Ray() {
97
+ const v2rayPath = path.join(BIN_DIR, V2RAY_BINARY);
98
+
99
+ // Check if already exists
100
+ if (existsSync(v2rayPath)) {
101
+ ok(`V2Ray found at ${v2rayPath}`);
102
+ // Verify companion files
103
+ for (const f of V2RAY_FILES) {
104
+ if (!existsSync(path.join(BIN_DIR, f))) {
105
+ warn(`Missing ${f} in bin/ — re-downloading`);
106
+ break;
107
+ }
108
+ }
109
+ if (V2RAY_FILES.every(f => existsSync(path.join(BIN_DIR, f)))) return;
110
+ }
111
+
112
+ // Check system-wide
113
+ const systemPaths = [
114
+ 'C:\\Program Files\\V2Ray\\v2ray.exe',
115
+ 'C:\\Program Files (x86)\\V2Ray\\v2ray.exe',
116
+ '/usr/local/bin/v2ray',
117
+ '/usr/bin/v2ray',
118
+ ];
119
+ for (const p of systemPaths) {
120
+ if (existsSync(p)) {
121
+ ok(`V2Ray found at ${p} (system install)`);
122
+ log('Tip: copy v2ray.exe + geoip.dat + geosite.dat to bin/ for portability');
123
+ return;
124
+ }
125
+ }
126
+
127
+ // Download
128
+ const platform = `${process.platform}-${process.arch}`;
129
+ const url = V2RAY_URLS[platform];
130
+ if (!url) {
131
+ warn(`No V2Ray binary available for ${platform}`);
132
+ warn(`Download manually from: https://github.com/v2fly/v2ray-core/releases/tag/v${V2RAY_VERSION}`);
133
+ warn(`Place v2ray${process.platform === 'win32' ? '.exe' : ''}, geoip.dat, geosite.dat in bin/`);
134
+ return;
135
+ }
136
+
137
+ mkdirSync(BIN_DIR, { recursive: true });
138
+ const zipPath = path.join(BIN_DIR, 'v2ray.zip');
139
+
140
+ log(`Downloading V2Ray v${V2RAY_VERSION} for ${platform}...`);
141
+ log(`URL: ${url}`);
142
+ await download(url, zipPath);
143
+
144
+ // SHA256 verification
145
+ const expectedHash = V2RAY_SHA256[platform];
146
+ if (expectedHash) {
147
+ const fileData = readFileSync(zipPath);
148
+ const actualHash = createHash('sha256').update(fileData).digest('hex');
149
+ if (actualHash !== expectedHash) {
150
+ unlinkSync(zipPath);
151
+ throw new Error(
152
+ `V2Ray SHA256 mismatch! Expected ${expectedHash}, got ${actualHash}. ` +
153
+ `Download may be corrupt or tampered. Delete bin/ and retry.`
154
+ );
155
+ }
156
+ ok('SHA256 checksum verified');
157
+ } else {
158
+ warn(`No SHA256 checksum for ${platform} — skipping verification`);
159
+ }
160
+
161
+ log('Extracting...');
162
+ unzip(zipPath, BIN_DIR);
163
+ unlinkSync(zipPath);
164
+
165
+ // Verify extraction + version check
166
+ if (existsSync(v2rayPath)) {
167
+ if (process.platform !== 'win32') {
168
+ execFileSync('chmod', ['+x', v2rayPath], { stdio: 'pipe' });
169
+ }
170
+ // Verify the binary runs and reports correct version
171
+ try {
172
+ const versionOut = execFileSync(v2rayPath, ['version'], { encoding: 'utf8', timeout: 10000, stdio: 'pipe' });
173
+ if (versionOut.includes(V2RAY_VERSION)) {
174
+ ok(`V2Ray v${V2RAY_VERSION} installed and verified`);
175
+ } else {
176
+ warn(`V2Ray binary reports unexpected version: ${versionOut.trim().split('\n')[0]}`);
177
+ }
178
+ } catch {
179
+ warn('V2Ray installed but version check failed (binary may not be executable on this platform)');
180
+ }
181
+ } else {
182
+ warn('V2Ray extraction failed — check bin/ directory');
183
+ }
184
+ }
185
+
186
+ // ─── WireGuard ──────────────────────────────────────────────────────────────
187
+
188
+ function findWireGuard() {
189
+ // Windows: check standard install paths
190
+ if (process.platform === 'win32') {
191
+ const paths = [
192
+ 'C:\\Program Files\\WireGuard\\wireguard.exe',
193
+ 'C:\\Program Files (x86)\\WireGuard\\wireguard.exe',
194
+ ];
195
+ for (const p of paths) {
196
+ if (existsSync(p)) return p;
197
+ }
198
+ }
199
+
200
+ // macOS/Linux: check wg-quick
201
+ if (process.platform !== 'win32') {
202
+ const paths = ['/usr/bin/wg', '/usr/local/bin/wg', '/opt/homebrew/bin/wg'];
203
+ for (const p of paths) {
204
+ if (existsSync(p)) return p;
205
+ }
206
+ }
207
+
208
+ // Check system PATH
209
+ try {
210
+ const cmd = process.platform === 'win32' ? 'where wireguard.exe' : 'which wg';
211
+ const result = execSync(cmd, { encoding: 'utf8', stdio: 'pipe' }).trim();
212
+ if (result) return result.split('\n')[0];
213
+ } catch { /* not in PATH */ }
214
+
215
+ return null;
216
+ }
217
+
218
+ function isAdmin() {
219
+ if (process.platform === 'win32') {
220
+ try {
221
+ execSync('net session', { stdio: 'pipe' });
222
+ return true;
223
+ } catch {
224
+ try {
225
+ execSync('fsutil dirty query C:', { stdio: 'pipe' });
226
+ return true;
227
+ } catch { return false; }
228
+ }
229
+ }
230
+ return process.getuid?.() === 0;
231
+ }
232
+
233
+ async function setupWireGuard() {
234
+ const existing = findWireGuard();
235
+ if (existing) {
236
+ ok(`WireGuard found at ${existing}`);
237
+ return;
238
+ }
239
+
240
+ // ─── Windows: auto-download MSI and silent install ───
241
+ if (process.platform === 'win32') {
242
+ const platform = `${process.platform}-${process.arch}`;
243
+ const msiUrl = WG_URLS[platform];
244
+
245
+ if (!msiUrl) {
246
+ warn(`No WireGuard MSI for ${platform}`);
247
+ log(`Download manually from: ${WG_INSTALL_URL}`);
248
+ return;
249
+ }
250
+
251
+ if (!isAdmin()) {
252
+ warn('WireGuard not installed — admin privileges required for automatic install');
253
+ log('Run setup as Administrator, or install manually:');
254
+ log(` Download: ${msiUrl}`);
255
+ log(` Install: msiexec /i wireguard-amd64-${WG_VERSION}.msi /qn /norestart`);
256
+ log('');
257
+ log('WireGuard is optional — V2Ray nodes (~70% of network) work without it');
258
+ return;
259
+ }
260
+
261
+ const msiPath = path.join(BIN_DIR, `wireguard-${WG_VERSION}.msi`);
262
+ mkdirSync(BIN_DIR, { recursive: true });
263
+
264
+ log(`Downloading WireGuard v${WG_VERSION} for ${platform}...`);
265
+ log(`URL: ${msiUrl}`);
266
+ await download(msiUrl, msiPath);
267
+
268
+ log('Installing WireGuard (silent)...');
269
+ try {
270
+ execSync(`msiexec /i "${msiPath}" /qn /norestart`, {
271
+ stdio: 'pipe',
272
+ timeout: 60000,
273
+ });
274
+
275
+ // Verify installation
276
+ const installed = findWireGuard();
277
+ if (installed) {
278
+ ok(`WireGuard v${WG_VERSION} installed at ${installed}`);
279
+ } else {
280
+ warn('WireGuard MSI completed but binary not found — may need reboot');
281
+ }
282
+ } catch (err) {
283
+ warn(`WireGuard MSI install failed: ${err.message}`);
284
+ log('Try installing manually:');
285
+ log(` msiexec /i "${msiPath}" /qn /norestart`);
286
+ }
287
+
288
+ // Clean up MSI
289
+ try { unlinkSync(msiPath); } catch { /* ignore */ }
290
+ return;
291
+ }
292
+
293
+ // ─── macOS: use Homebrew ───
294
+ if (process.platform === 'darwin') {
295
+ try {
296
+ execSync('which brew', { stdio: 'pipe' });
297
+ log('Installing WireGuard via Homebrew...');
298
+ execSync('brew install wireguard-tools', { stdio: 'inherit', timeout: 120000 });
299
+ ok('WireGuard installed via Homebrew');
300
+ return;
301
+ } catch {
302
+ warn('WireGuard not found and Homebrew not available');
303
+ log('Install Homebrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"');
304
+ log('Then: brew install wireguard-tools');
305
+ return;
306
+ }
307
+ }
308
+
309
+ // ─── Linux: use package manager ───
310
+ if (process.platform === 'linux') {
311
+ const managers = [
312
+ { cmd: 'apt-get', install: 'sudo apt-get install -y wireguard-tools' },
313
+ { cmd: 'dnf', install: 'sudo dnf install -y wireguard-tools' },
314
+ { cmd: 'pacman', install: 'sudo pacman -S --noconfirm wireguard-tools' },
315
+ { cmd: 'apk', install: 'sudo apk add wireguard-tools' },
316
+ ];
317
+
318
+ for (const mgr of managers) {
319
+ try {
320
+ execSync(`which ${mgr.cmd}`, { stdio: 'pipe' });
321
+ if (isAdmin()) {
322
+ log(`Installing WireGuard via ${mgr.cmd}...`);
323
+ execSync(mgr.install, { stdio: 'inherit', timeout: 120000 });
324
+ ok('WireGuard installed');
325
+ } else {
326
+ warn('WireGuard not installed — root required');
327
+ log(`Install: ${mgr.install}`);
328
+ }
329
+ return;
330
+ } catch { /* try next manager */ }
331
+ }
332
+
333
+ warn('WireGuard not found and no supported package manager detected');
334
+ log('Install wireguard-tools for your distribution');
335
+ }
336
+ }
337
+
338
+ // ─── npm dependencies ───────────────────────────────────────────────────────
339
+
340
+ function checkDeps() {
341
+ if (!existsSync(path.join(__dirname, 'node_modules'))) {
342
+ log('Installing npm dependencies...');
343
+ execSync('npm install', { cwd: __dirname, stdio: 'inherit' });
344
+ ok('Dependencies installed');
345
+ } else {
346
+ ok('npm dependencies present');
347
+ }
348
+ }
349
+
350
+ // ─── Main ───────────────────────────────────────────────────────────────────
351
+
352
+ async function main() {
353
+ console.log('');
354
+ console.log(' Sentinel dVPN SDK — Setup');
355
+ console.log(' ─────────────────────────');
356
+ console.log('');
357
+
358
+ checkDeps();
359
+ await setupV2Ray();
360
+ await setupWireGuard();
361
+
362
+ console.log('');
363
+ console.log(' Setup complete! Quick start:');
364
+ console.log('');
365
+ console.log(' import { connect, listNodes, registerCleanupHandlers } from \'./index.js\';');
366
+ console.log('');
367
+ console.log(' registerCleanupHandlers();');
368
+ console.log(' const nodes = await listNodes();');
369
+ console.log(' const conn = await connect({ mnemonic: \'...\', nodeAddress: nodes[0].address });');
370
+ console.log('');
371
+ }
372
+
373
+ main().catch(err => {
374
+ console.error(`[setup] Fatal: ${err.message}`);
375
+ process.exit(1);
376
+ });