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.
- package/CHANGELOG.md +446 -0
- package/LICENSE +21 -0
- package/README.md +75 -0
- package/ai-path/ADMIN-ELEVATION.md +116 -0
- package/ai-path/AI-MANIFESTO.md +185 -0
- package/ai-path/BREAKING.md +74 -0
- package/ai-path/CHECKLIST.md +619 -0
- package/ai-path/CONNECTION-STEPS.md +724 -0
- package/ai-path/DECISION-TREE.md +378 -0
- package/ai-path/DEPENDENCIES.md +459 -0
- package/ai-path/E2E-FLOW.md +1555 -0
- package/ai-path/FAILURES.md +403 -0
- package/ai-path/GUIDE.md +1217 -0
- package/ai-path/README.md +558 -0
- package/ai-path/SPLIT-TUNNEL.md +266 -0
- package/ai-path/cli.js +535 -0
- package/ai-path/connect.js +884 -0
- package/ai-path/discover.js +178 -0
- package/ai-path/environment.js +266 -0
- package/ai-path/errors.js +86 -0
- package/ai-path/examples/autonomous-agent.mjs +220 -0
- package/ai-path/examples/multi-region.mjs +174 -0
- package/ai-path/examples/one-shot.mjs +31 -0
- package/ai-path/index.js +60 -0
- package/ai-path/pricing.js +136 -0
- package/ai-path/recommend.js +413 -0
- package/ai-path/run-admin.vbs +25 -0
- package/ai-path/setup.js +291 -0
- package/ai-path/wallet.js +137 -0
- package/app-helpers.js +363 -0
- package/app-settings.js +95 -0
- package/app-types.js +267 -0
- package/audit.js +847 -0
- package/batch.js +293 -0
- package/bin/setup.js +376 -0
- package/chain/authz.js +109 -0
- package/chain/broadcast.js +472 -0
- package/chain/client.js +160 -0
- package/chain/fee-grants.js +305 -0
- package/chain/index.js +891 -0
- package/chain/lcd.js +313 -0
- package/chain/queries.js +547 -0
- package/chain/rpc.js +408 -0
- package/chain/wallet.js +141 -0
- package/cli/config.js +143 -0
- package/cli/index.js +463 -0
- package/cli/output.js +182 -0
- package/cli.js +491 -0
- package/client/index.js +251 -0
- package/client.js +271 -0
- package/config/index.js +255 -0
- package/connection/connect.js +849 -0
- package/connection/disconnect.js +180 -0
- package/connection/discovery.js +321 -0
- package/connection/index.js +76 -0
- package/connection/proxy.js +148 -0
- package/connection/resilience.js +428 -0
- package/connection/security.js +232 -0
- package/connection/state.js +369 -0
- package/connection/tunnel.js +691 -0
- package/consumer.js +132 -0
- package/cosmjs-setup.js +1884 -0
- package/defaults.js +366 -0
- package/disk-cache.js +107 -0
- package/dist/client.d.ts +108 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +400 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/errors/index.js +112 -0
- package/errors.js +218 -0
- package/examples/README.md +64 -0
- package/examples/connect-direct.mjs +106 -0
- package/examples/connect-plan.mjs +125 -0
- package/examples/error-handling.mjs +109 -0
- package/examples/query-nodes.mjs +94 -0
- package/examples/wallet-basics.mjs +61 -0
- package/generated/amino/amino.ts +9 -0
- package/generated/cosmos/base/v1beta1/coin.ts +365 -0
- package/generated/cosmos_proto/cosmos.ts +323 -0
- package/generated/gogoproto/gogo.ts +9 -0
- package/generated/google/protobuf/descriptor.ts +7601 -0
- package/generated/google/protobuf/duration.ts +208 -0
- package/generated/google/protobuf/timestamp.ts +238 -0
- package/generated/sentinel/lease/v1/events.ts +924 -0
- package/generated/sentinel/lease/v1/lease.ts +292 -0
- package/generated/sentinel/lease/v1/msg.ts +949 -0
- package/generated/sentinel/lease/v1/params.ts +164 -0
- package/generated/sentinel/node/v3/events.ts +881 -0
- package/generated/sentinel/node/v3/msg.ts +1002 -0
- package/generated/sentinel/node/v3/node.ts +263 -0
- package/generated/sentinel/node/v3/params.ts +183 -0
- package/generated/sentinel/plan/v3/events.ts +675 -0
- package/generated/sentinel/plan/v3/msg.ts +1191 -0
- package/generated/sentinel/plan/v3/plan.ts +283 -0
- package/generated/sentinel/provider/v2/events.ts +171 -0
- package/generated/sentinel/provider/v2/msg.ts +480 -0
- package/generated/sentinel/provider/v2/params.ts +131 -0
- package/generated/sentinel/provider/v2/provider.ts +246 -0
- package/generated/sentinel/session/v3/events.ts +480 -0
- package/generated/sentinel/session/v3/msg.ts +616 -0
- package/generated/sentinel/session/v3/params.ts +260 -0
- package/generated/sentinel/session/v3/proof.ts +180 -0
- package/generated/sentinel/session/v3/session.ts +384 -0
- package/generated/sentinel/subscription/v3/events.ts +1181 -0
- package/generated/sentinel/subscription/v3/msg.ts +1305 -0
- package/generated/sentinel/subscription/v3/params.ts +167 -0
- package/generated/sentinel/subscription/v3/subscription.ts +315 -0
- package/generated/sentinel/types/v1/bandwidth.ts +124 -0
- package/generated/sentinel/types/v1/price.ts +149 -0
- package/generated/sentinel/types/v1/renewal.ts +87 -0
- package/generated/sentinel/types/v1/status.ts +54 -0
- package/generated/typeRegistry.ts +27 -0
- package/index.js +486 -0
- package/node-connect.js +3015 -0
- package/operator.js +134 -0
- package/package.json +113 -0
- package/plan-operations.js +199 -0
- package/preflight.js +352 -0
- package/pricing/index.js +262 -0
- package/proto/amino/amino.proto +84 -0
- package/proto/cosmos/base/v1beta1/coin.proto +61 -0
- package/proto/cosmos_proto/cosmos.proto +112 -0
- package/proto/gogoproto/gogo.proto +145 -0
- package/proto/google/api/annotations.proto +31 -0
- package/proto/google/api/http.proto +370 -0
- package/proto/google/protobuf/any.proto +106 -0
- package/proto/google/protobuf/duration.proto +115 -0
- package/proto/google/protobuf/timestamp.proto +145 -0
- package/proto/sentinel/lease/v1/events.proto +52 -0
- package/proto/sentinel/lease/v1/genesis.proto +15 -0
- package/proto/sentinel/lease/v1/lease.proto +25 -0
- package/proto/sentinel/lease/v1/msg.proto +62 -0
- package/proto/sentinel/lease/v1/params.proto +17 -0
- package/proto/sentinel/node/v3/events.proto +50 -0
- package/proto/sentinel/node/v3/genesis.proto +15 -0
- package/proto/sentinel/node/v3/msg.proto +63 -0
- package/proto/sentinel/node/v3/node.proto +27 -0
- package/proto/sentinel/node/v3/params.proto +21 -0
- package/proto/sentinel/node/v3/querier.proto +63 -0
- package/proto/sentinel/plan/v3/events.proto +41 -0
- package/proto/sentinel/plan/v3/genesis.proto +21 -0
- package/proto/sentinel/plan/v3/msg.proto +83 -0
- package/proto/sentinel/plan/v3/plan.proto +32 -0
- package/proto/sentinel/plan/v3/querier.proto +53 -0
- package/proto/sentinel/provider/v2/events.proto +16 -0
- package/proto/sentinel/provider/v2/genesis.proto +15 -0
- package/proto/sentinel/provider/v2/msg.proto +35 -0
- package/proto/sentinel/provider/v2/params.proto +17 -0
- package/proto/sentinel/provider/v2/provider.proto +24 -0
- package/proto/sentinel/provider/v3/genesis.proto +15 -0
- package/proto/sentinel/provider/v3/params.proto +13 -0
- package/proto/sentinel/session/v3/events.proto +30 -0
- package/proto/sentinel/session/v3/genesis.proto +15 -0
- package/proto/sentinel/session/v3/msg.proto +50 -0
- package/proto/sentinel/session/v3/params.proto +25 -0
- package/proto/sentinel/session/v3/proof.proto +25 -0
- package/proto/sentinel/session/v3/querier.proto +100 -0
- package/proto/sentinel/session/v3/session.proto +50 -0
- package/proto/sentinel/subscription/v2/allocation.proto +21 -0
- package/proto/sentinel/subscription/v2/payout.proto +22 -0
- package/proto/sentinel/subscription/v3/events.proto +65 -0
- package/proto/sentinel/subscription/v3/genesis.proto +17 -0
- package/proto/sentinel/subscription/v3/msg.proto +83 -0
- package/proto/sentinel/subscription/v3/params.proto +21 -0
- package/proto/sentinel/subscription/v3/subscription.proto +33 -0
- package/proto/sentinel/types/v1/bandwidth.proto +19 -0
- package/proto/sentinel/types/v1/price.proto +21 -0
- package/proto/sentinel/types/v1/renewal.proto +21 -0
- package/proto/sentinel/types/v1/status.proto +16 -0
- package/protocol/encoding.js +341 -0
- package/protocol/events.js +361 -0
- package/protocol/handshake.js +297 -0
- package/protocol/index.js +15 -0
- package/protocol/messages.js +346 -0
- package/protocol/plans.js +199 -0
- package/protocol/v2ray.js +268 -0
- package/protocol/v3.js +723 -0
- package/protocol/wireguard.js +125 -0
- package/security/index.js +132 -0
- package/session-manager.js +329 -0
- package/session-tracker.js +80 -0
- package/setup.js +376 -0
- package/speedtest/index.js +528 -0
- package/speedtest.js +567 -0
- package/src/client.ts +502 -0
- package/src/index.ts +20 -0
- package/state/index.js +347 -0
- package/state.js +516 -0
- package/test-all-chain-ops.js +493 -0
- package/test-all-logic.js +199 -0
- package/test-all-msg-types.js +292 -0
- package/test-every-connection.js +208 -0
- package/test-feegrant-connect.js +98 -0
- package/test-logic.js +148 -0
- package/test-mainnet.js +176 -0
- package/test-plan-lifecycle.js +335 -0
- package/tls-trust.js +132 -0
- package/tsconfig.build.json +20 -0
- package/tsconfig.json +34 -0
- package/types/chain.d.ts +746 -0
- package/types/connection.d.ts +425 -0
- package/types/errors.d.ts +174 -0
- package/types/index.d.ts +1380 -0
- package/types/nodes.d.ts +187 -0
- package/types/pricing.d.ts +156 -0
- package/types/protocol.d.ts +332 -0
- package/types/session.d.ts +236 -0
- package/types/settings.d.ts +192 -0
- package/v3protocol.js +1053 -0
- package/wallet/index.js +153 -0
- package/wireguard.js +307 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
# SDK Changelog, Fixes & Danger Warnings
|
|
2
|
+
|
|
3
|
+
Every fix made during SDK creation, why it matters, and what happens if you use upstream Sentinel code directly without these fixes.
|
|
4
|
+
|
|
5
|
+
## Documentation Versions
|
|
6
|
+
|
|
7
|
+
| Version | Date | Changes |
|
|
8
|
+
|---------|------|---------|
|
|
9
|
+
| v1 | 2026-03-06 | Initial SDK docs — 16 doc files, 6 code files |
|
|
10
|
+
| v2 | 2026-03-07 | Added tutorials.md, benchmarks.md, migration-v2-v3.md. Score 96/100 |
|
|
11
|
+
| v3 | 2026-03-07 | 35 AI-readiness gaps identified (8 blockers, 11 high, 16 medium/low) |
|
|
12
|
+
| v4 | 2026-03-08 | Deep failure analysis: 6 code bugs fixed, 6 docs updated. Score 98/100 |
|
|
13
|
+
| v5 | 2026-03-08 | All 8 blockers + all 11 highs + all mediums/lows addressed. Score 100/100 |
|
|
14
|
+
| v6 | 2026-03-08 | AI validation fix: `remote_addrs` vs `remote_url` LCD field name mismatch |
|
|
15
|
+
| v7 | 2026-03-08 | Comprehensive re-audit: session nesting fix, httpbin.org removal, waitForPort in examples, taskkill /IM warnings, base_session docs |
|
|
16
|
+
| v8 | 2026-03-08 | **Pre-validation + auto-detection**: `findV2RayExe()` searches system for existing v2ray.exe before demanding download. `validateTunnelRequirements()` runs BEFORE paying. |
|
|
17
|
+
| v9 | 2026-03-08 | **Tunnel verification**: `installWgTunnel()` now verifies service reaches RUNNING state (catches silent failures). `setupWireGuard()` verifies actual connectivity through tunnel. `connectDirect()` NEVER returns success unless traffic flows. |
|
|
18
|
+
| v10 | 2026-03-08 | **Full overhaul from AI builder feedback (Test1)**: `fullTunnel: true` default, stale session auto-retry, V2Ray auto system proxy, `onProgress`/`opts.log`, kill v2ray by PID, WG config→ProgramData, `checkPortFree()`, V2Ray orphan cleanup, all docs updated |
|
|
19
|
+
| v11 | 2026-03-08 | **Deep feedback round 2**: `forceNewSession` option for shared wallets, `queryOnlineNodes()` quality scoring (WG>V2Ray, drift penalty, peer count), shared wallet docs in known-issues.md, "Using Primitives Directly" section in end-to-end, `qualityScore` field in node results |
|
|
20
|
+
| v12 | 2026-03-08 | **Plug-and-play**: `index.js` single entry point, `setup.js` auto-downloads V2Ray/checks WG, `state.js` crash recovery with `saveState`/`loadState`/`recoverOrphans`, `package.json` gets `main`/`bin`/`scripts`, `disconnect()` clears state, `registerCleanupHandlers()` auto-recovers orphans, `buildV2RayClientConfig()` auto-filters grpc/tls outbounds (0% success rate) |
|
|
21
|
+
| v13 | 2026-03-08 | **Session tracking + PID files**: Poisoned session tracking (`markSessionPoisoned`/`isSessionPoisoned`) — `findExistingSession` auto-skips failed sessions, no more P2P waste on retry loops. PID file helpers (`writePidFile`/`checkPidFile`/`clearPidFile`) for server process management. All docs updated to use `index.js` imports (`connect`, `listNodes`). Express pattern shows PID file usage |
|
|
22
|
+
| v14 | 2026-03-08 | **Deep review fixes**: VMess/VLess clock drift intelligence (flag in connectDirect, post-handshake VLess check in setupV2Ray, VMess-only+drift>120s fails fast). Pre-connection TCP port probe skips dead outbound ports in 3s. README quickstart updated to `index.js`+`setup.js`+`listNodes`. Benchmarks updated to 708-node data. v2ray-config.md transport_security enum fully documented. plan-lifecycle.md WARNING about inactive default. PREFLIGHT.md references setup.js |
|
|
23
|
+
| v15 | 2026-03-08 | **Cold-start audit + critical bug fix**: Fixed `opts.nodeAddress` ReferenceError crash in `setupV2Ray()` — V2Ray connections would crash after tunnel setup. Fixed `require('http')` in ESM `setup.js`. README rewritten with "Zero to VPN" getting-started. PREFLIGHT.md adds wallet/funding checklist. Import path clarified. `nodeAddress` properly threaded through `tunnelOpts→performHandshake→setupV2Ray` |
|
|
24
|
+
| v16 | 2026-03-08 | **Hardcoded defaults + endpoint fallback**: New `defaults.js` — single source of truth for all static values with timestamps. Auto-fallback through 5 RPC and 4 LCD endpoints. Known broken nodes auto-filtered. README "Hardcoded Defaults" section. Prepared for future RPC query server |
|
|
25
|
+
| v17 | 2026-03-08 | **Testing documentation + example scripts**: New `testing.md` — complete testing methodology from 708-node scan (parallel scanning, batch payment, transport fallback, speed testing, error classification, result structure, all constants). New `js-sdk/examples/probe.js` (single-node diagnostic) and `js-sdk/examples/diagnose.js` (batch N WG + N V2Ray test). README updated with 13 code files, examples section, testing topic in index |
|
|
26
|
+
| v18 | 2026-03-08 | **npm-ready + test suite + 5 bug fixes + 4 doc fixes**: Full npm packaging (`npm install sentinel-dvpn-sdk`). `package.json` with exports map, engines, keywords, files, repository, license. MIT license. `.npmignore` for clean 46KB package. `postinstall` auto-runs `setup.js`. `SDK_VERSION` export. 190-assertion smoke test suite (`npm test`). `dotenv` moved to devDependency. **Bug fixes:** (1) `BigInt(null)` crash in node-connect.js, (2) `protoInt64` dropped BigInt zero `0n`, (3) `wg-quick` detection broken, (4) `checkIsAdmin` Windows-only, (5) `emergencyCleanupSync` no-op on Linux/macOS. **Doc fixes:** (1) grpc/tls "auto-filtered" → "auto-removed unless sole transport", (2) "exponential backoff" → "linear backoff", (3) `fetch()` in pricing.md/migration-v2-v3.md → `axios`, (4) tutorials.md `remote_url` clarified with `fetchActiveNodes()` resolution comment, httpbin removed from testing.md targets |
|
|
27
|
+
| v19 | 2026-03-09 | **Security hardening + command injection + key zeroing**: All 27 `execSync` template calls → `execFileSync` with argument arrays. State file validation (`validateStateValues`). WireGuard conf ACL on directory. WG private key zeroed after config write. Empty security catches now log warnings. Configurable timeouts (`opts.timeouts`). CosmJS types in TypeScript. Registry backup/restore for system proxy. Input validation at API boundary. 206-assertion test suite |
|
|
28
|
+
| v20 | 2026-03-09 | **Architecture overhaul (Meta + DARPA/NSA audit fixes)**: (1) **Typed errors** — `SentinelError`, `ValidationError`, `NodeError`, `ChainError`, `TunnelError`, `SecurityError` with machine-readable `.code` and `.details`. `ErrorCodes` constants. (2) **TOFU TLS** — Trust-On-First-Use certificate pinning for node connections (`tls-trust.js`). Eliminates MITM attack on handshake (was DARPA #1 finding, CVSS 9.1). (3) **EventEmitter** — `events` export emits `connecting`, `connected`, `disconnected`, `error`, `progress`, `log`. No more polling `getStatus()`. (4) **AbortController** — `opts.signal` cancels in-progress connections at any step. (5) **Key zeroing** — Cosmos private key (`privKey.fill(0)`) zeroed after handshake, WG key zeroed after config write. (6) **Code dedup** — `connectInternal()` shared flow eliminates 80% duplication between `connectDirect`/`connectViaPlan`. (7) **Structured logging** — `progress()` emits structured `{ event, detail, ts }` objects via EventEmitter. 108 exports, 251-assertion test suite |
|
|
29
|
+
| v21 | 2026-03-09 | **Performance + SentinelClient class (Telegram audit fixes)**: (1) **Reduced sleeps** — WG: exponential retry at 1.5s/3s/5s instead of flat 5s. V2Ray: 2s instead of 5s (outbound loop has own checks). Saves 3-6s per connection. (2) **Parallel setup** — wallet+privKey in Promise.all, RPC+LCD in Promise.all, balance fire-and-forget. Saves 2-4s. (3) **Wallet cache** — `cachedCreateWallet()` keyed by SHA256(mnemonic). Saves 300ms on reconnect. (4) **Node list cache** — `queryOnlineNodes()` cached 5min with background refresh. Instant repeat calls. (5) **SentinelClient class** — Instantiable wrapper with per-instance EventEmitter, DI, cached wallet/client. See `CHANGES-v21.md` for full debugging guide. 109 exports, 275-assertion test suite |
|
|
30
|
+
| v22 | 2026-03-09 | **V2Ray config fixes from 780-node test**: (1) **QUIC fix** — global+per-outbound `quicSettings` changed from `chacha20-poly1305` to `security: 'none'` matching sentinel-go-sdk server. Was 0/4 (0%). (2) **v2-format metadata mapping** — nodes returning v2 fields mapped to v3 equivalents instead of throwing. Recovers TCSR-Station (48 peers). (3) **Transport priority** — sort order from 780-node data: grpc/none 58→87%, QUIC last. (4) **Handshake timeout** — 30s→45s for distant/loaded nodes. (5) **defaults.js rates** — updated to 780-node data. (6) **extremeDrift VLess preference** — outbounds re-sorted to put VLess before VMess when drift >120s. 109 exports, 289-assertion test suite |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## CRITICAL FIXES (Will cause silent failures or data loss)
|
|
35
|
+
|
|
36
|
+
### -1. Pre-validation + Auto-detection: Binary/Driver Check Before Payment — ADDED (v8)
|
|
37
|
+
|
|
38
|
+
**What we changed:** Added `findV2RayExe()` and `validateTunnelRequirements()` to `node-connect.js`. Both `connectDirect()` and `connectViaPlan()` call validation BEFORE broadcasting any payment TX.
|
|
39
|
+
|
|
40
|
+
**Auto-detection:** Instead of just checking the provided path, `findV2RayExe()` searches the entire system for an existing v2ray.exe installation:
|
|
41
|
+
1. Explicit path passed by caller
|
|
42
|
+
2. `bin/v2ray.exe` relative to CWD
|
|
43
|
+
3. Other Sentinel project directories on Desktop (`sentinel-node-tester/bin/`, `web-proxy/bin/`)
|
|
44
|
+
4. Standard install locations (`C:\Program Files\V2Ray\`, `/usr/local/bin/`)
|
|
45
|
+
5. `V2RAY_PATH` environment variable
|
|
46
|
+
6. System PATH (`where v2ray.exe` / `which v2ray`)
|
|
47
|
+
|
|
48
|
+
If found elsewhere, it logs `"V2Ray binary found at: <path> (auto-detected)"` and uses it — no redundant download. WireGuard already had equivalent detection in `wireguard.js` (searches Program Files, PATH, `WIREGUARD_PATH` env). If nothing found anywhere, throws with clear error. No P2P spent either way.
|
|
49
|
+
|
|
50
|
+
**What the code did before v8:** `connectDirect()` paid for a session (broadcast TX → P2P deducted) BEFORE checking if the tunnel binary existed. For V2Ray nodes, it would create a session, try to spawn a non-existent `v2ray.exe`, fail with ENOENT or "All V2Ray transport/protocol combinations failed", and the user's P2P was gone with no tunnel.
|
|
51
|
+
|
|
52
|
+
**Why it's dangerous:** Every failed V2Ray connection attempt burned P2P tokens. An app with no `bin/v2ray.exe` would hemorrhage P2P — paying for sessions it could never use. Two separate AIs built apps from this SDK and BOTH had this failure mode: wallet/nodes/UI worked fine, but clicking "Connect" either silently wasted P2P or threw cryptic errors. The connection — the ONLY thing that matters — was broken from day one.
|
|
53
|
+
|
|
54
|
+
**Found by:** Two independent app builds (Antigravity/Gemini, Test1) both failed at the connection step despite having correct handshake/signing code. Root cause was identical: missing V2Ray binary.
|
|
55
|
+
|
|
56
|
+
### 0. LCD `remote_addrs` vs `remote_url` — RESOLVED (v6)
|
|
57
|
+
|
|
58
|
+
**What we changed:** Added `resolveNodeUrl(node)` to cosmjs-setup.js. `fetchActiveNodes()` now adds a computed `remote_url` field to each node. lcd-endpoints.md updated to show the real field name.
|
|
59
|
+
|
|
60
|
+
**What the LCD actually returns:** `remote_addrs: ["185.47.255.36:52618"]` — an array of `"IP:PORT"` strings with NO `https://` protocol prefix.
|
|
61
|
+
|
|
62
|
+
**What the docs showed before v6:** `remote_url: "https://IP:PORT"` — a string with protocol prefix. This field does not exist in the v3 LCD response.
|
|
63
|
+
|
|
64
|
+
**Why it's dangerous:** Code that reads `node.remote_url` from raw LCD data gets `undefined`. All `nodeStatusV3()` calls fail with timeouts/errors. Result: **0 node connections**, with misleading "timeout" errors that look like the nodes are offline when the real problem is the URL is undefined.
|
|
65
|
+
|
|
66
|
+
**Found by:** Another AI (Gemini) building a complete app from the SDK docs. Initial result was 0/10 connections. After the AI independently discovered the field name mismatch, it achieved 9/10.
|
|
67
|
+
|
|
68
|
+
### 1. V2Ray Balancer Session Poisoning — REMOVED
|
|
69
|
+
|
|
70
|
+
**What we changed:** `buildV2RayClientConfig()` in v3protocol.js no longer generates a `leastping` balancer. It routes directly to the highest-priority outbound.
|
|
71
|
+
|
|
72
|
+
**What the upstream code does:** The official sentinel-go-sdk `client.json.tmpl` uses a leastping balancer with observatory. The V2Ray 5.2.1 binary supports this.
|
|
73
|
+
|
|
74
|
+
**Why it's dangerous:** When V2Ray connects to a node via transport A (e.g., grpc), gets killed, then reconnects via transport B (e.g., tcp) with the same UUID, the node has a stale VMess/VLess session from transport A. The balancer silently picks whichever transport "won" the latency probe — which may be the stale one. Result: connection opens, zero data flows, no error message. We saw this on 40%+ of V2Ray reconnections during testing.
|
|
75
|
+
|
|
76
|
+
**What happens if you revert:** Intermittent silent failures. Speed tests return 0 Mbps with no error. Appears to work on first connection but fails on subsequent ones.
|
|
77
|
+
|
|
78
|
+
**The fix:** Test each outbound individually with a fresh V2Ray process per attempt. Kill v2ray, wait 2s for port release, write config with single outbound, spawn new process, test connectivity. First working outbound wins.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### 2. Windows TIME_WAIT Port Cascading — ROTATING PORTS
|
|
83
|
+
|
|
84
|
+
**What we changed:** SOCKS port rotates: `10800 + Math.floor(Math.random() * 1000)`. API port rotates: `10000 + Math.floor(Math.random() * 50000)`.
|
|
85
|
+
|
|
86
|
+
**What upstream code does:** sentinel-go-sdk uses fixed ports (1080 SOCKS, 2080 API).
|
|
87
|
+
|
|
88
|
+
**Why it's dangerous:** When V2Ray binds port 1080 and gets killed (or crashes), Windows keeps the port in TIME_WAIT for ~240 seconds. Next V2Ray launch on port 1080 fails: `"bind: Only one usage of each socket address"`. Every subsequent test fails until the port frees. In a testing scenario with 400+ nodes, this cascades into dozens of false failures.
|
|
89
|
+
|
|
90
|
+
**What happens if you revert:** On Windows, any V2Ray restart within 4 minutes of the previous one fails. On Linux this is less severe (TIME_WAIT is shorter) but still possible.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
### 3. Native `fetch()` Silently Ignores SOCKS5 Proxy
|
|
95
|
+
|
|
96
|
+
**What we changed:** All speed tests and proxy-routed HTTP use `axios` with `socks-proxy-agent`, never native `fetch()`.
|
|
97
|
+
|
|
98
|
+
**What upstream/naive code does:** Node.js `fetch(url, { agent })` — the agent option is silently ignored by native fetch.
|
|
99
|
+
|
|
100
|
+
**Why it's dangerous:** Your speed test appears to work perfectly — but the traffic bypasses the VPN entirely and goes through your direct internet connection. You measure your own ISP speed, not the VPN. No error, no warning. We discovered this when "VPN speeds" matched raw connection speeds exactly.
|
|
101
|
+
|
|
102
|
+
**What happens if you revert:** All speed measurements are wrong. You'll report your ISP speed as VPN speed. Connectivity tests pass even when the tunnel is broken.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### 4. WireGuard Tunnel Cleanup — EMERGENCY HANDLERS
|
|
107
|
+
|
|
108
|
+
**What we changed:** `registerCleanupHandlers()` installs exit/SIGINT/SIGTERM/uncaughtException handlers that call `emergencyCleanupSync()`. Also runs cleanup on startup (kills stale tunnels from previous crash).
|
|
109
|
+
|
|
110
|
+
**What upstream code doesn't do:** No crash recovery. If your app crashes with an active WireGuard tunnel, the tunnel stays installed. On Windows, `AllowedIPs = 0.0.0.0/0` routes ALL traffic through the dead tunnel. Result: **total internet death** until you manually uninstall the tunnel service.
|
|
111
|
+
|
|
112
|
+
**What happens if you skip this:** One crash = no internet. Users must open Services, find `WireGuard Tunnel: wgsent0`, stop and delete it manually. Non-technical users will think their computer is broken.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### 5. Signature Must Be Exactly 64 Bytes
|
|
117
|
+
|
|
118
|
+
**What we changed:** `sig.toFixedLength().slice(0, 64)` — strip recovery byte.
|
|
119
|
+
|
|
120
|
+
**What happens with 65 bytes:** Go's `VerifySignature` on the node checks `len(sig) != 64` and returns false. Handshake fails with HTTP 403 "signature verification failed". No explanation in error message about why.
|
|
121
|
+
|
|
122
|
+
**What upstream docs say:** The Go SDK uses `crypto/ecdsa` which handles this natively. The JavaScript `@cosmjs/crypto` Secp256k1 returns 65 bytes (r + s + recovery). Every JS implementation must strip the last byte.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### 6. VMess Clock Drift > 120s = Silent Auth Failure
|
|
127
|
+
|
|
128
|
+
**What we changed:** `nodeStatusV3()` measures clock drift from the HTTP `Date` header. `connectDirect()` rejects V2Ray nodes with |drift| > 120s.
|
|
129
|
+
|
|
130
|
+
**What upstream code doesn't do:** No clock check. VMess AEAD authentication uses the client's timestamp. If the node's clock differs by more than 120 seconds, auth silently fails. The connection opens, the handshake succeeds, but no data flows.
|
|
131
|
+
|
|
132
|
+
**What happens if you skip this:** ~5-10% of V2Ray nodes have drifted clocks. You'll spend hours debugging "why does the handshake succeed but speed test returns 0?" — it's always clock drift for VMess nodes. VLess is unaffected (no timestamp auth).
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## HIGH SEVERITY FIXES (Will cause TX failures or incorrect behavior)
|
|
137
|
+
|
|
138
|
+
### 7. `max_price` Must Be Passed in Direct Session TX
|
|
139
|
+
|
|
140
|
+
**What we changed:** `connectDirect()` now fetches the node's `gigabyte_prices` from LCD and passes the exact price as `max_price` in `MsgStartSessionRequest`.
|
|
141
|
+
|
|
142
|
+
**What happens without it:** The chain may reject the TX or use a default that doesn't match the node's price. Some nodes have multiple price denoms — you must specify which one.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### 8. `encodeDuration()` Was Never Defined
|
|
147
|
+
|
|
148
|
+
**What we changed:** Created `encodeDuration({ seconds, nanos })` in plan-operations.js. Also added to protobuf-encoding.md.
|
|
149
|
+
|
|
150
|
+
**What the upstream SDK provides:** The Go SDK handles Duration encoding via protobuf code generation. The JS SDK had no equivalent. The `MsgCreatePlanRequest` encoder referenced `encodeDuration()` but the function didn't exist anywhere.
|
|
151
|
+
|
|
152
|
+
**What happens without it:** Anyone trying to create a plan gets `ReferenceError: encodeDuration is not defined`. Complete blocker for the plan management flow.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
### 9. `@cosmjs/encoding` Was Missing from Dependencies
|
|
157
|
+
|
|
158
|
+
**What we changed:** Added `@cosmjs/encoding` to package.json.
|
|
159
|
+
|
|
160
|
+
**Why it matters:** `fromBech32()` and `toBech32()` are required for address prefix conversion (sent ↔ sentprov ↔ sentnode). Without this package, any provider/plan operation fails because you can't construct the `sentprov` address.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
### 10. Provider LCD Endpoint is v2, Not v3
|
|
165
|
+
|
|
166
|
+
**What we documented:** `/sentinel/provider/v2/providers` — NOT v3.
|
|
167
|
+
|
|
168
|
+
**What happens with v3:** HTTP 501 "Not Implemented". The v3 provider gRPC-gateway routes were never registered on the LCD. This is an upstream chain issue (sentinelhub v12.0.0). If you follow the pattern of other endpoints (all v3), you'll get 501 for providers.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### 11. Plan Query Endpoints Return 501
|
|
173
|
+
|
|
174
|
+
**What we documented:** `/sentinel/plan/v3/plans` returns 501 Not Implemented.
|
|
175
|
+
|
|
176
|
+
**Why this matters:** You cannot query plan details (bytes, prices, duration, private flag) via LCD REST API. The gRPC service exists in chain source but the gateway routes are not registered. Plan discovery must happen through subscription events or off-chain data.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
### 12. UUID is Integer Byte Array, NOT String
|
|
181
|
+
|
|
182
|
+
**What we changed:** Documented and coded: V2Ray handshake sends `{ uuid: [0x12, 0x34, ...] }` — an array of 16 integers, not a UUID string.
|
|
183
|
+
|
|
184
|
+
**What happens with a string:** The node's Go code unmarshals `uuid` as `[]byte`. A JSON string would be decoded differently than an integer array. The handshake succeeds but V2Ray can't authenticate because the UUID doesn't match.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
### 13. `Secp256k1.makeKeypair` vs `nobleSecp.getPublicKey`
|
|
189
|
+
|
|
190
|
+
**What we fixed:** node-handshake.md was referencing `@cosmjs/crypto`'s `Secp256k1.makeKeypair()` but the actual production code uses `@noble/curves/secp256k1`'s `getPublicKey(privKey, true)`.
|
|
191
|
+
|
|
192
|
+
**Why it matters:** `Secp256k1.makeKeypair` is async and returns `{ pubkey, privkey }`. `nobleSecp.getPublicKey` is sync and returns the pubkey directly. Mixing these up causes type errors or incorrect key encoding.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## MEDIUM SEVERITY FIXES
|
|
197
|
+
|
|
198
|
+
### 14. `node.exe` Kill Protection
|
|
199
|
+
|
|
200
|
+
**NEVER run `taskkill /F /IM node.exe`** on Windows. This kills your own Node.js process, VS Code terminals, and anything else running on Node. Kill V2Ray by image name (`v2ray.exe`) or specific processes by PID only.
|
|
201
|
+
|
|
202
|
+
### 15. Removed Unused `dotenv` from SDK Dependencies
|
|
203
|
+
|
|
204
|
+
SDK code files never import dotenv. It's an app-level concern. Including it in SDK deps implies the SDK handles .env loading, which it doesn't.
|
|
205
|
+
|
|
206
|
+
### 16. `grpc/tls` Has 0% Success Rate
|
|
207
|
+
|
|
208
|
+
From 400+ node tests: grpc with TLS security NEVER works. grpc/none works ~58% of the time. If your transport selection doesn't deprioritize grpc/tls, you'll waste time on connections that will never succeed.
|
|
209
|
+
|
|
210
|
+
### 17. Plan-lifecycle.md Referenced Undefined `lcd()` Helper
|
|
211
|
+
|
|
212
|
+
The doc used `await lcd('/sentinel/...')` as a function call, but no such helper existed in any code file. Replaced with actual `axios.get()` calls.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## IMPROVEMENTS MADE
|
|
217
|
+
|
|
218
|
+
| # | Improvement | Impact |
|
|
219
|
+
|---|-------------|--------|
|
|
220
|
+
| 1 | Created `cosmjs-setup.js` — wallet, registry, signing client, all 13 msg types | Can now send ANY Sentinel TX from one import |
|
|
221
|
+
| 2 | Created `plan-operations.js` — 10 encoder functions + proto primitives | Plan management was impossible without this |
|
|
222
|
+
| 3 | Created `node-connect.js` — full connect orchestration | 30-line quickstart instead of 300+ lines of glue code |
|
|
223
|
+
| 4 | Exported proto primitives from plan-operations.js | Others can build custom encoders without duplicating code |
|
|
224
|
+
| 5 | Added `MSG_TYPES` constant with all 13 type URLs | No more copy-pasting long type URL strings |
|
|
225
|
+
| 6 | Added `broadcast()` helper with default fee | Eliminates gas estimation round-trip |
|
|
226
|
+
| 7 | Added `fetchActiveNodes()` with pagination | Properly handles 900+ nodes across multiple LCD pages |
|
|
227
|
+
| 8 | Auto-resolve speedtest IPs for WireGuard split tunnel | WireGuard now auto-configures safe split tunneling |
|
|
228
|
+
| 9 | `connectViaPlan()` returns `subscriptionId` | Can manage subscription after connection |
|
|
229
|
+
| 10 | Transport priority sort by real success rates | tcp/ws first (100%), grpc/tls last (0%) |
|
|
230
|
+
| 11 | Windows setup guide with exact binary versions/URLs | No guessing which V2Ray version or where to get it |
|
|
231
|
+
| 12 | Networking stack explanation (WireGuard vs V2Ray flows) | Understand what happens at each layer |
|
|
232
|
+
| 13 | Added `createSafeBroadcaster()` — mutex + retry | Prevents sequence mismatch on rapid TXs |
|
|
233
|
+
| 14 | Added `parseChainError()` — 13+ error patterns | User-friendly errors instead of raw chain logs |
|
|
234
|
+
| 15 | Added `lcd()` helper — LCD REST with error checking | Consistent query pattern, checks gRPC codes in body |
|
|
235
|
+
| 16 | Added `discoverPlanIds()` — plan discovery workaround | Works around 501 on /plan/v3/plans endpoint |
|
|
236
|
+
| 17 | Added `getDvpnPrice()` — CoinGecko with 5-min cache | USD cost estimation for UX |
|
|
237
|
+
| 18 | Created `advanced-patterns.md` — batch TX, auto-lease, session mgmt | Production reliability patterns documented |
|
|
238
|
+
| 19 | Updated `findExistingSession()` — uses lcd() + base_session | Correct session nesting, consistent HTTP client |
|
|
239
|
+
| 20 | Updated `fetchActiveNodes()` — uses lcd() helper | Consistent error handling across all LCD queries |
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## VERSION LOCKS (Do Not Upgrade Without Testing)
|
|
244
|
+
|
|
245
|
+
| Dependency | Locked Version | Why |
|
|
246
|
+
|------------|---------------|-----|
|
|
247
|
+
| V2Ray | **5.2.1 exactly** | v5.44.1 has observatory bugs that break leastping (even though we removed balancer, future users might add it back) |
|
|
248
|
+
| CosmJS | **0.32.x** | v0.33+ may change Registry API or signing behavior |
|
|
249
|
+
| sentinelhub | **v12.0.0** | Message type URLs and field numbers are chain-version-specific |
|
|
250
|
+
| Node.js | **20+ LTS** | crypto.randomUUID() requires Node 19+, ESM import requires 14+ |
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## DANGER: Importing Code Directly from Sentinel GitHub
|
|
255
|
+
|
|
256
|
+
If you clone sentinel-official repos and try to use their code directly:
|
|
257
|
+
|
|
258
|
+
1. **sentinel-go-sdk** — Go code. Cannot be used in JavaScript. The `client.json.tmpl` is a Go template, not valid JSON. You must understand the template variables and translate.
|
|
259
|
+
|
|
260
|
+
2. **sentinel-js-sdk** — Limited v3 support. Most message types are not implemented. Uses older CosmJS patterns. Does not handle the v3 handshake protocol.
|
|
261
|
+
|
|
262
|
+
3. **dvpn-node** — Server-side Go code. Useful for understanding the handshake protocol, but you'll need to reverse-engineer the request/response format from Go structs.
|
|
263
|
+
|
|
264
|
+
4. **hub** — Proto definitions. If you try to use `protoc` codegen, you'll need the entire Cosmos SDK proto tree. Our manual encoding approach avoids this entirely.
|
|
265
|
+
|
|
266
|
+
The safest path is using this SDK's code files, which have been tested against 400+ live nodes on the actual chain.
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## FIXES FROM DEEP FAILURE ANALYSIS (March 2026)
|
|
271
|
+
|
|
272
|
+
Deep inspection of 26 node test failures (SOCKS5 no connectivity, fetch failed, ETIMEDOUT) revealed 6 bugs across the SDK. All fixed.
|
|
273
|
+
|
|
274
|
+
### 21. Axios "fetch failed" — Force HTTP Adapter
|
|
275
|
+
|
|
276
|
+
**What we changed:** Added `axios.defaults.adapter = 'http'` to v3protocol.js, speedtest.js, and node-connect.js.
|
|
277
|
+
|
|
278
|
+
**Root cause:** On Node.js v18+, axios 1.7+ includes `fetch` (undici) in its default adapter list. Undici throws opaque `"fetch failed"` for ALL network errors — ECONNREFUSED, ETIMEDOUT, ENOTFOUND are collapsed into one useless string. The `http` adapter preserves error codes.
|
|
279
|
+
|
|
280
|
+
**Impact:** 10 out of 26 failures showed as bare `"fetch failed"` with zero diagnostic context. The actual cause was CosmJS using native fetch for RPC calls during broadcast.
|
|
281
|
+
|
|
282
|
+
**What happens if you revert:** Opaque error messages. Network failures are undiagnosable. You can't tell if a node is offline, DNS failed, or the RPC endpoint is down.
|
|
283
|
+
|
|
284
|
+
### 22. V2-Format Metadata Detection
|
|
285
|
+
|
|
286
|
+
**What we changed:** `buildV2RayClientConfig()` now detects old v2 metadata format (`{port, protocol, ca, tls}`) and throws immediately instead of silently building a broken config.
|
|
287
|
+
|
|
288
|
+
**Root cause:** Some nodes still run old software returning v2 metadata. `proxy_protocol` is undefined → defaults to vmess, `transport_protocol` is undefined → defaults to tcp. The config "builds" but routes nothing.
|
|
289
|
+
|
|
290
|
+
**Impact:** 1 out of 26 failures. The node appeared to have a working SOCKS5 proxy that just couldn't reach the internet.
|
|
291
|
+
|
|
292
|
+
**What happens if you revert:** Silent config generation. V2Ray starts, SOCKS5 port opens, but traffic is black-holed because the outbound config doesn't match what the node expects.
|
|
293
|
+
|
|
294
|
+
### 23. Handshake Error Wrappers — Include errno
|
|
295
|
+
|
|
296
|
+
**What we changed:** Both `initHandshakeV3()` and `initHandshakeV3V2Ray()` catch blocks now include `err.code` (ECONNREFUSED, ETIMEDOUT, etc.) alongside HTTP status.
|
|
297
|
+
|
|
298
|
+
**Before:** `"Node handshake failed (HTTP undefined): fetch failed"` — useless.
|
|
299
|
+
**After:** `"Node handshake failed (HTTP undefined, ECONNREFUSED): connect ECONNREFUSED 1.2.3.4:443"` — actionable.
|
|
300
|
+
|
|
301
|
+
### 24. SOCKS5 Readiness Probe (waitForPort)
|
|
302
|
+
|
|
303
|
+
**What we changed:** Added `waitForPort()` — TCP port probe that replaces fixed `sleep(6000)` before SOCKS5 testing. Returns when the port is accepting connections or times out.
|
|
304
|
+
|
|
305
|
+
**Root cause:** V2Ray SOCKS5 binding takes variable time (2-8s+). Fixed sleep was either too short (false failure) or too long (wasted time).
|
|
306
|
+
|
|
307
|
+
**Impact:** 15 SOCKS5 "no internet connectivity" failures included nodes where V2Ray wasn't ready when the test ran.
|
|
308
|
+
|
|
309
|
+
### 25. Connectivity Retry in speedtest.js Phase 0
|
|
310
|
+
|
|
311
|
+
**What we changed:** Phase 0 (Google/Cloudflare/1.1.1.1 HEAD check) now retries once after a 3-second pause if all targets fail.
|
|
312
|
+
|
|
313
|
+
**Root cause:** Even after `waitForPort()` confirms SOCKS5 is listening, the proxy pipeline may not be fully warmed up. A single retry catches this.
|
|
314
|
+
|
|
315
|
+
### 26. node-connect.js — Replace httpbin.org with Reliable Targets
|
|
316
|
+
|
|
317
|
+
**What we changed:** `setupV2Ray()` connectivity test now uses `https://www.google.com` and `https://www.cloudflare.com` (HEAD requests) instead of `https://httpbin.org/ip` (GET).
|
|
318
|
+
|
|
319
|
+
**Root cause:** httpbin.org has frequent outages and rate limits. Google/Cloudflare are more reliable and match the targets used in speedtest.js.
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## FIXES FROM AI BUILDER FEEDBACK (v10, March 2026)
|
|
324
|
+
|
|
325
|
+
An AI built a full desktop app (Test1) from the SDK and wrote `SDK-SUGGESTIONS.md` documenting 8 issues. All 8 are now fixed.
|
|
326
|
+
|
|
327
|
+
### 27. Full Tunnel by Default — `fullTunnel` Option
|
|
328
|
+
|
|
329
|
+
**What we changed:** Added `fullTunnel` option to `connectDirect()` and `connectViaPlan()`. Default is `true` — WireGuard writes `AllowedIPs = 0.0.0.0/0, ::/0` which routes ALL traffic through VPN and changes the user's IP.
|
|
330
|
+
|
|
331
|
+
**What the code did before:** `splitIPs || null` → if caller passes `[]` (empty array, truthy), the SDK tried `resolveSpeedtestIPs()` which only routed 3 speedtest IPs. User's browser IP never changed. The empty-array-is-truthy ambiguity confused both AIs and humans.
|
|
332
|
+
|
|
333
|
+
**New behavior:**
|
|
334
|
+
- `fullTunnel: true` (default) → full tunnel, user's IP changes
|
|
335
|
+
- `fullTunnel: false` → split tunnel with speedtest IPs only (safe for testing)
|
|
336
|
+
- `splitIPs: ['1.2.3.4']` → explicit IPs, overrides fullTunnel
|
|
337
|
+
|
|
338
|
+
### 28. Stale Session Auto-Retry
|
|
339
|
+
|
|
340
|
+
**What we changed:** `connectDirect()` now catches "already exists in database" errors during handshake, automatically pays for a fresh session, and retries.
|
|
341
|
+
|
|
342
|
+
**What the code did before:** If `findExistingSession()` returned a stale session (paid but handshake already registered on node), the handshake threw HTTP 409 and `connectDirect()` propagated the error. The user lost P2P (session already paid) and got a cryptic error.
|
|
343
|
+
|
|
344
|
+
**Why it matters:** Every failed connection leaves a stale session on-chain. Next connection attempt finds it via `findExistingSession()`, tries to reuse it, and fails with "already exists". Without auto-retry, every subsequent connection attempt fails until the session expires.
|
|
345
|
+
|
|
346
|
+
### 29. V2Ray System Proxy Auto-Set
|
|
347
|
+
|
|
348
|
+
**What we changed:** Added `setSystemProxy(port)` and `clearSystemProxy()`. When `systemProxy: true` (default), `setupV2Ray()` auto-sets the Windows system SOCKS proxy via registry after a working outbound is found. `cleanup()` and `disconnect()` auto-clear it. Exit handlers also clear proxy.
|
|
349
|
+
|
|
350
|
+
**What the code did before:** V2Ray created a local SOCKS5 proxy on `127.0.0.1:PORT` but nothing in the system was configured to use it. The user connected "successfully" but their browser still used the direct connection. IP didn't change.
|
|
351
|
+
|
|
352
|
+
**Cross-platform:** `setSystemProxy`/`clearSystemProxy` are no-ops on non-Windows. On macOS/Linux, the caller should handle proxy configuration (networksetup / gsettings).
|
|
353
|
+
|
|
354
|
+
### 30. Progress Callbacks
|
|
355
|
+
|
|
356
|
+
**What we changed:** Added `onProgress: (step, detail) => void` option to `connectDirect()` and `connectViaPlan()`. Steps: `wallet`, `node-check`, `validate`, `session`, `handshake`, `tunnel`, `verify`, `proxy`.
|
|
357
|
+
|
|
358
|
+
**Why it matters:** `connectDirect()` is a ~30-second operation. Without progress feedback, the UI shows nothing — the user thinks the app is frozen. Now apps can show "Checking node...", "Paying...", "Installing tunnel...", etc.
|
|
359
|
+
|
|
360
|
+
### 31. Kill V2Ray by PID, Not Image Name
|
|
361
|
+
|
|
362
|
+
**What we changed:** Replaced `execSync('taskkill /F /IM v2ray.exe')` with `activeV2RayProc.kill()` (kill by PID).
|
|
363
|
+
|
|
364
|
+
**What the code did before:** `taskkill /F /IM v2ray.exe` kills ALL v2ray.exe processes system-wide. If the user had other V2Ray instances (personal VPN, other apps), they all got killed.
|
|
365
|
+
|
|
366
|
+
### 32. WireGuard Config Written to SYSTEM-Readable Path
|
|
367
|
+
|
|
368
|
+
**What we changed:** `writeWgConfig()` in v3protocol.js now writes to `C:\ProgramData\sentinel-wg\` on Windows instead of `os.tmpdir()` (user temp).
|
|
369
|
+
|
|
370
|
+
**What the code did before:** Config was written to `C:\Users\X\AppData\Local\Temp\sentinel-wg\wgsent0.conf`. The WireGuard service runs as the SYSTEM account, which often can't read files from a user's temp directory. The service registered but never started — silent failure caught only by the v9 `verifyTunnelRunning()` check.
|
|
371
|
+
|
|
372
|
+
**Now:** `C:\ProgramData\` is readable by all accounts including SYSTEM. The tunnel actually starts.
|
|
373
|
+
|
|
374
|
+
### 33. System Proxy Cleanup in Exit Handlers
|
|
375
|
+
|
|
376
|
+
**What we changed:** `registerCleanupHandlers()` now calls `clearSystemProxy()` in all exit handlers (exit, SIGINT, SIGTERM, uncaughtException). `disconnect()` also clears proxy.
|
|
377
|
+
|
|
378
|
+
**What the code did before:** If the app crashed with V2Ray running, the Windows system proxy stayed set to a dead SOCKS port. All browser traffic failed until the user manually cleared the proxy in Windows settings.
|
|
379
|
+
|
|
380
|
+
### 34. Custom Logger Support (`opts.log`)
|
|
381
|
+
|
|
382
|
+
**What we changed:** Added `log` option to `connectDirect()` and `connectViaPlan()`. All SDK output routes through this function. Default: `console.log`.
|
|
383
|
+
|
|
384
|
+
**What the code did before:** All SDK functions used `console.log` directly. When running as a background service with `nohup`, logs disappeared or went to the wrong place. Apps couldn't route SDK logs to their own logging system, UI, or file.
|
|
385
|
+
|
|
386
|
+
**New behavior:**
|
|
387
|
+
```js
|
|
388
|
+
const conn = await connectDirect({
|
|
389
|
+
...opts,
|
|
390
|
+
log: (msg) => myAppLog(msg), // route all SDK output here
|
|
391
|
+
onProgress: (step, detail) => updateUI(step, detail), // structured progress
|
|
392
|
+
});
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### 35. Port Conflict Detection (`checkPortFree`)
|
|
396
|
+
|
|
397
|
+
**What we changed:** Added `checkPortFree(port)` export. Returns a Promise<boolean> — true if port is free.
|
|
398
|
+
|
|
399
|
+
**Why it matters:** When the old server process wasn't killed properly, restarting silently fails to bind the port. The new process starts, all requests go to the old code, and nothing in the logs indicates this. Use at startup:
|
|
400
|
+
```js
|
|
401
|
+
if (!await checkPortFree(3000)) {
|
|
402
|
+
console.error('Port 3000 in use — is another server running?');
|
|
403
|
+
process.exit(1);
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### 36. V2Ray Orphan Cleanup in Exit Handlers
|
|
408
|
+
|
|
409
|
+
**What we changed:** `registerCleanupHandlers()` now calls `killOrphanV2Ray()` which kills the tracked V2Ray process by PID. Previously, `emergencyCleanupSync()` only cleaned up WireGuard tunnels — a crashed app would leave a zombie v2ray.exe running.
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## FIXES FROM DEEP AI BUILDER FEEDBACK ROUND 2 (v11, March 2026)
|
|
414
|
+
|
|
415
|
+
Second pass through Test1's SDK-SUGGESTIONS.md (expanded to 16 items with v10 status annotations and 72/100 AI buildability score).
|
|
416
|
+
|
|
417
|
+
### 37. `forceNewSession` Option
|
|
418
|
+
|
|
419
|
+
**What we changed:** Added `forceNewSession: true` option to `connectDirect()`. When set, skips `findExistingSession()` entirely and always pays for a fresh session.
|
|
420
|
+
|
|
421
|
+
**Why it matters:** When multiple apps share one wallet (e.g., desktop app + node tester), `findExistingSession()` picks up sessions created by other apps. Those sessions have already been handshaked with a different UUID/keypair, causing "already exists in database" errors. The auto-retry in v10 handles this by paying again, but it still wastes one session's worth of P2P per attempt. `forceNewSession: true` skips the lookup entirely — zero wasted sessions.
|
|
422
|
+
|
|
423
|
+
### 38. Built-in Node Quality Scoring
|
|
424
|
+
|
|
425
|
+
**What we changed:** `queryOnlineNodes()` now returns a `qualityScore` (0-100) per node and sorts results best-first by default. Scoring based on 400+ node test results:
|
|
426
|
+
- WireGuard nodes: +20 (simpler tunnel, fewer failure modes)
|
|
427
|
+
- Clock drift >120s: -40 (VMess will fail silently)
|
|
428
|
+
- Clock drift >60s: -15 (risky for VMess)
|
|
429
|
+
- 0 peers: +10 (empty = fast)
|
|
430
|
+
- 20+ peers: -10 (congested)
|
|
431
|
+
|
|
432
|
+
**What the code did before:** `queryOnlineNodes()` returned nodes in random order. An AI building an app didn't know to avoid grpc/tls nodes (0% success), high-drift nodes (VMess death), or heavily loaded nodes unless it read 300 lines of known-issues.md. Now `nodes[0]` is the best available node.
|
|
433
|
+
|
|
434
|
+
Pass `sort: false` to get random order (useful for load distribution).
|
|
435
|
+
|
|
436
|
+
### 39. Shared Wallet Documentation
|
|
437
|
+
|
|
438
|
+
**What we changed:** Added "CRITICAL: Shared Wallet — Multiple Apps, Same Mnemonic" section to known-issues.md. Documents the 409 error cascade, the `forceNewSession` fix, and recommends separate wallets per app in production.
|
|
439
|
+
|
|
440
|
+
Also documented WireGuard full tunnel DNS behavior (`writeWgConfig` adds OpenDNS only for full tunnel, uses system DNS for split tunnel).
|
|
441
|
+
|
|
442
|
+
### 40. "Using Primitives Directly" Documentation
|
|
443
|
+
|
|
444
|
+
**What we changed:** Added a new section in end-to-end-example.md showing how to use the SDK's low-level functions directly for apps that need custom control over each step. Documents that `connectDirect()` is a convenience wrapper, not a requirement.
|
|
445
|
+
|
|
446
|
+
**Why it matters:** The AI that built Test1 abandoned `connectDirect()` entirely and used primitives. The building blocks were production-grade but this wasn't documented as a supported pattern. Now it is.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sentinel dVPN Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Sentinel dVPN SDK — JavaScript
|
|
2
|
+
|
|
3
|
+
The official JavaScript SDK for the [Sentinel](https://sentinel.co) decentralized VPN network. WireGuard + V2Ray tunnels, Cosmos blockchain, 1000+ nodes across 70+ countries. No API keys. No accounts. No servers to trust.
|
|
4
|
+
|
|
5
|
+
**Also available:** [C# SDK](https://github.com/Sentinel-Autonomybuilder/sentinel-dvpn-sdk-csharp) | [AI Connect](https://github.com/Sentinel-Autonomybuilder/sentinel-ai-connect) (zero-config wrapper)
|
|
6
|
+
|
|
7
|
+
> **For AI agents:** If you just want to connect to a VPN with one function call, use [`sentinel-ai-connect`](https://www.npmjs.com/package/sentinel-ai-connect) instead. This SDK is for developers building custom applications.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
> **AI Agent Instructions**
|
|
12
|
+
>
|
|
13
|
+
> ```bash
|
|
14
|
+
> # Install as a dependency in YOUR project — do NOT clone or publish
|
|
15
|
+
> npm install sentinel-dvpn-sdk
|
|
16
|
+
> ```
|
|
17
|
+
>
|
|
18
|
+
> **DO NOT run `npm publish`.** You are a consumer, not a maintainer.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install sentinel-dvpn-sdk
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
import { connectAuto, disconnect, registerCleanupHandlers } from 'sentinel-dvpn-sdk';
|
|
32
|
+
|
|
33
|
+
registerCleanupHandlers();
|
|
34
|
+
|
|
35
|
+
const result = await connectAuto({
|
|
36
|
+
mnemonic: process.env.MNEMONIC,
|
|
37
|
+
serviceType: 'wireguard',
|
|
38
|
+
onProgress: (step, detail) => console.log(`[${step}] ${detail}`),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
console.log(`Connected: session ${result.sessionId}, IP changed`);
|
|
42
|
+
|
|
43
|
+
await disconnect();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## For AI Agents
|
|
47
|
+
|
|
48
|
+
Use [sentinel-ai-connect](https://www.npmjs.com/package/sentinel-ai-connect) — a zero-config wrapper with one function call from zero to encrypted tunnel.
|
|
49
|
+
|
|
50
|
+
## Features
|
|
51
|
+
|
|
52
|
+
- **WireGuard** kernel-level encrypted tunnels (requires admin)
|
|
53
|
+
- **V2Ray** SOCKS5 proxy with transport obfuscation (no admin needed)
|
|
54
|
+
- **Split tunneling** — per-app (V2Ray SOCKS5) or per-destination (WireGuard AllowedIPs)
|
|
55
|
+
- **276 exports** — wallet, chain, handshake, tunnel, security, pricing, state
|
|
56
|
+
- **Cosmos blockchain** — on-chain sessions, P2P token payments
|
|
57
|
+
- **4 LCD + 5 RPC failover endpoints** — no single point of failure
|
|
58
|
+
- **AES-256-GCM** encrypted credential storage
|
|
59
|
+
- **TOFU TLS** certificate pinning
|
|
60
|
+
- **Verify-before-capture** — safe WireGuard activation without killing internet
|
|
61
|
+
|
|
62
|
+
## Security
|
|
63
|
+
|
|
64
|
+
- All private keys zeroed with `Buffer.fill(0)` after use
|
|
65
|
+
- Credentials encrypted at rest (AES-256-GCM)
|
|
66
|
+
- File permissions 0o600 on all sensitive files
|
|
67
|
+
- See [SECURITY.md](https://github.com/Sentinel-Autonomybuilder/sentinel-dvpn-sdk/blob/main/SECURITY.md)
|
|
68
|
+
|
|
69
|
+
## Documentation
|
|
70
|
+
|
|
71
|
+
Full documentation, protocol specs, and examples at [github.com/Sentinel-Autonomybuilder/sentinel-dvpn-sdk](https://github.com/Sentinel-Autonomybuilder/sentinel-dvpn-sdk).
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
MIT — built on [Sentinel.co](https://sentinel.co)
|