blue-js-sdk 2.4.0 → 2.6.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/README.md +3 -3
- package/chain/fee-grants.js +196 -0
- package/chain/index.js +8 -2
- package/chain/queries.js +105 -3
- package/chain/rpc.js +58 -2
- package/client.js +17 -1
- package/connection/connect.js +17 -5
- package/connection/disconnect.js +86 -10
- package/connection/index.js +2 -0
- package/cosmjs-setup.js +26 -2
- package/index.js +5 -1
- package/node-connect.js +101 -13
- package/operator.js +2 -0
- package/package.json +2 -5
- package/types/index.d.ts +2 -2
- package/ai-path/ADMIN-ELEVATION.md +0 -116
- package/ai-path/AI-MANIFESTO.md +0 -185
- package/ai-path/BREAKING.md +0 -74
- package/ai-path/CHECKLIST.md +0 -619
- package/ai-path/CONNECTION-STEPS.md +0 -724
- package/ai-path/DECISION-TREE.md +0 -422
- package/ai-path/DEPENDENCIES.md +0 -459
- package/ai-path/E2E-FLOW.md +0 -1707
- package/ai-path/FAILURES.md +0 -410
- package/ai-path/GUIDE.md +0 -1315
- package/ai-path/README.md +0 -599
- package/ai-path/SPLIT-TUNNEL.md +0 -266
- package/ai-path/cli.js +0 -548
- package/ai-path/connect.js +0 -1028
- package/ai-path/discover.js +0 -178
- package/ai-path/environment.js +0 -266
- package/ai-path/errors.js +0 -86
- package/ai-path/examples/autonomous-agent.mjs +0 -220
- package/ai-path/examples/multi-region.mjs +0 -174
- package/ai-path/examples/one-shot.mjs +0 -31
- package/ai-path/index.js +0 -79
- package/ai-path/pricing.js +0 -137
- package/ai-path/recommend.js +0 -413
- package/ai-path/run-admin.vbs +0 -25
- package/ai-path/setup.js +0 -291
- package/ai-path/wallet.js +0 -137
package/connection/disconnect.js
CHANGED
|
@@ -28,13 +28,35 @@ import { queryNode, privKeyFromMnemonic } from '../cosmjs-setup.js';
|
|
|
28
28
|
import { createNodeHttpsAgent } from '../tls-trust.js';
|
|
29
29
|
|
|
30
30
|
// ─── Disconnect ──────────────────────────────────────────────────────────────
|
|
31
|
+
//
|
|
32
|
+
// TWO DISCONNECT PATHS — CHOOSE INTENT EXPLICITLY.
|
|
33
|
+
//
|
|
34
|
+
// Soft: disconnect() / disconnectState(state)
|
|
35
|
+
// - Tears down the local tunnel (WireGuard/V2Ray) and cleans up system state.
|
|
36
|
+
// - Leaves the on-chain session in status=1 (active).
|
|
37
|
+
// - Next connectDirect() to the SAME node reuses the session via
|
|
38
|
+
// findExistingSession — no new MsgStartSession TX, no new payment, bandwidth preserved.
|
|
39
|
+
// - Use when: user is pausing, network changed, closing the app temporarily.
|
|
40
|
+
//
|
|
41
|
+
// Hard: disconnectAndEndSession() / disconnectStateAndEndSession(state)
|
|
42
|
+
// - Tears down the tunnel AND broadcasts MsgCancelSession on chain.
|
|
43
|
+
// - Session moves status=1 → settling → refund after ~2h settlement window.
|
|
44
|
+
// - Use when: user is done with this node, switching nodes permanently,
|
|
45
|
+
// or wants the bandwidth deposit back.
|
|
46
|
+
//
|
|
47
|
+
// Internal: _disconnectInternal(state, { endSession })
|
|
48
|
+
// - Caller MUST pass endSession explicitly as true or false.
|
|
49
|
+
// - No default — forces intentional choice at every callsite.
|
|
31
50
|
|
|
32
51
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
52
|
+
* Internal disconnect implementation. Caller must explicitly pass endSession.
|
|
53
|
+
* @param {object} state - ConnectionState instance
|
|
54
|
+
* @param {{ endSession: boolean }} opts
|
|
55
|
+
* endSession: true → broadcast MsgCancelSession (hard disconnect)
|
|
56
|
+
* endSession: false → preserve on-chain session for reuse (soft disconnect)
|
|
57
|
+
* @private
|
|
35
58
|
*/
|
|
36
|
-
|
|
37
|
-
export async function disconnectState(state) {
|
|
59
|
+
async function _disconnectInternal(state, { endSession }) {
|
|
38
60
|
// v30: Signal any running connectAuto() retry loop to abort, and release the
|
|
39
61
|
// connection lock so the user can reconnect after disconnect completes.
|
|
40
62
|
setAbortConnect(true);
|
|
@@ -65,11 +87,18 @@ export async function disconnectState(state) {
|
|
|
65
87
|
try { disableDnsLeakPrevention(); } catch (e) { console.warn('[sentinel-sdk] DNS restore warning:', e.message); }
|
|
66
88
|
}
|
|
67
89
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
90
|
+
if (endSession) {
|
|
91
|
+
// Hard disconnect: broadcast MsgCancelSession — session settles and refunds deposit.
|
|
92
|
+
if (prev?.sessionId && state._mnemonic) {
|
|
93
|
+
_endSessionOnChain(prev.sessionId, state._mnemonic).catch(e => {
|
|
94
|
+
console.warn(`[sentinel-sdk] Failed to end session ${prev.sessionId} on chain: ${e.message}`);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
// Soft disconnect: leave session on chain in status=1 for reuse.
|
|
99
|
+
if (prev?.sessionId) {
|
|
100
|
+
console.log(`[sentinel-sdk] Session ${prev.sessionId} preserved on chain (status=1) for future reuse — no MsgCancelSession broadcast.`);
|
|
101
|
+
}
|
|
73
102
|
}
|
|
74
103
|
} finally {
|
|
75
104
|
// ALWAYS clear connection state — even if teardown threw
|
|
@@ -82,8 +111,55 @@ export async function disconnectState(state) {
|
|
|
82
111
|
}
|
|
83
112
|
}
|
|
84
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Soft disconnect — tear down the local tunnel, leave the on-chain session active.
|
|
116
|
+
*
|
|
117
|
+
* A subsequent connectDirect() to the SAME node will reuse the session via
|
|
118
|
+
* findExistingSession — no new MsgStartSession TX, no new payment, remaining
|
|
119
|
+
* bandwidth is preserved.
|
|
120
|
+
*
|
|
121
|
+
* Use when: user is pausing, network changed, or closing the app temporarily.
|
|
122
|
+
* To settle the session on-chain and reclaim the unused deposit, use
|
|
123
|
+
* disconnectAndEndSession() instead.
|
|
124
|
+
*
|
|
125
|
+
* @param {object} [state] - ConnectionState instance (defaults to _defaultState)
|
|
126
|
+
*/
|
|
127
|
+
export async function disconnectState(state) {
|
|
128
|
+
return _disconnectInternal(state, { endSession: false });
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Soft disconnect (default state) — tear down the tunnel, leave on-chain session active.
|
|
133
|
+
*
|
|
134
|
+
* @see disconnectState
|
|
135
|
+
*/
|
|
85
136
|
export async function disconnect() {
|
|
86
|
-
return
|
|
137
|
+
return _disconnectInternal(_defaultState, { endSession: false });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Hard disconnect — tear down the tunnel AND broadcast MsgCancelSession on chain.
|
|
142
|
+
*
|
|
143
|
+
* The session settles after the ~2h inactive_pending window. The node refunds
|
|
144
|
+
* the unused portion of the bandwidth deposit (for peer-to-peer sessions).
|
|
145
|
+
* For plan-based sessions, this stops metering against the plan allocation.
|
|
146
|
+
*
|
|
147
|
+
* Use when: user is done with this node (switching nodes permanently, ending
|
|
148
|
+
* their session, or wants the deposit back).
|
|
149
|
+
*
|
|
150
|
+
* @param {object} [state] - ConnectionState instance (defaults to _defaultState)
|
|
151
|
+
*/
|
|
152
|
+
export async function disconnectStateAndEndSession(state) {
|
|
153
|
+
return _disconnectInternal(state, { endSession: true });
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Hard disconnect (default state) — tear down the tunnel AND broadcast MsgCancelSession.
|
|
158
|
+
*
|
|
159
|
+
* @see disconnectStateAndEndSession
|
|
160
|
+
*/
|
|
161
|
+
export async function disconnectAndEndSession() {
|
|
162
|
+
return _disconnectInternal(_defaultState, { endSession: true });
|
|
87
163
|
}
|
|
88
164
|
|
|
89
165
|
// ─── Cleanup Registration ───────────────────────────────────────────────────
|
package/connection/index.js
CHANGED
package/cosmjs-setup.js
CHANGED
|
@@ -87,6 +87,8 @@ import {
|
|
|
87
87
|
getExpiringGrants as _getExpiringGrants,
|
|
88
88
|
renewExpiringGrants as _renewExpiringGrants,
|
|
89
89
|
monitorFeeGrants as _monitorFeeGrants,
|
|
90
|
+
streamGrantPlanSubscribers as _streamGrantPlanSubscribers,
|
|
91
|
+
computeFeeGrantGasCosts as _computeFeeGrantGasCosts,
|
|
90
92
|
} from './chain/fee-grants.js';
|
|
91
93
|
|
|
92
94
|
// ─── Input Validation Helpers ────────────────────────────────────────────────
|
|
@@ -485,9 +487,15 @@ export async function getBalance(client, address) {
|
|
|
485
487
|
* Returns session ID (BigInt) or null. Use this to avoid double-paying.
|
|
486
488
|
*
|
|
487
489
|
* Note: Sessions have a nested base_session object containing the actual data.
|
|
490
|
+
*
|
|
491
|
+
* @param {string} lcdUrl - LCD endpoint URL
|
|
492
|
+
* @param {string} walletAddr - sent1... wallet address
|
|
493
|
+
* @param {string} nodeAddr - sentnode1... node address
|
|
494
|
+
* @param {object} [opts] - Optional. Pass `{ onStaleDuplicate: (BigInt) => void }` to
|
|
495
|
+
* receive fire-and-forget cancellation callbacks for stale duplicate sessions.
|
|
488
496
|
*/
|
|
489
|
-
export async function findExistingSession(lcdUrl, walletAddr, nodeAddr) {
|
|
490
|
-
return _findExistingSession(lcdUrl, walletAddr, nodeAddr);
|
|
497
|
+
export async function findExistingSession(lcdUrl, walletAddr, nodeAddr, opts) {
|
|
498
|
+
return _findExistingSession(lcdUrl, walletAddr, nodeAddr, opts);
|
|
491
499
|
}
|
|
492
500
|
|
|
493
501
|
/**
|
|
@@ -1006,6 +1014,22 @@ export function monitorFeeGrants(opts = {}) {
|
|
|
1006
1014
|
return _monitorFeeGrants(opts);
|
|
1007
1015
|
}
|
|
1008
1016
|
|
|
1017
|
+
/**
|
|
1018
|
+
* Stream progress as we grant fee allowances to all plan subscribers in batches.
|
|
1019
|
+
* Async generator. See chain/fee-grants.js for event shapes.
|
|
1020
|
+
*/
|
|
1021
|
+
export function streamGrantPlanSubscribers(planId, opts = {}) {
|
|
1022
|
+
return _streamGrantPlanSubscribers(planId, opts);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* Sum udvpn fees the granter has paid on behalf of a plan's subscribers.
|
|
1027
|
+
* Iterates subscribers, pulls TX history, filters on fee.granter.
|
|
1028
|
+
*/
|
|
1029
|
+
export async function computeFeeGrantGasCosts(planId, opts = {}) {
|
|
1030
|
+
return _computeFeeGrantGasCosts(planId, opts);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1009
1033
|
// ─── Query Helpers (v25c) ────────────────────────────────────────────────────
|
|
1010
1034
|
|
|
1011
1035
|
/**
|
package/index.js
CHANGED
|
@@ -27,6 +27,9 @@ export {
|
|
|
27
27
|
enrichNodes,
|
|
28
28
|
buildNodeIndex,
|
|
29
29
|
disconnect,
|
|
30
|
+
disconnectAndEndSession,
|
|
31
|
+
disconnectState,
|
|
32
|
+
disconnectStateAndEndSession,
|
|
30
33
|
isConnected,
|
|
31
34
|
getStatus,
|
|
32
35
|
registerCleanupHandlers,
|
|
@@ -52,7 +55,6 @@ export {
|
|
|
52
55
|
disableDnsLeakPrevention,
|
|
53
56
|
events,
|
|
54
57
|
ConnectionState,
|
|
55
|
-
disconnectState,
|
|
56
58
|
tryFastReconnect,
|
|
57
59
|
} from './node-connect.js';
|
|
58
60
|
|
|
@@ -311,6 +313,7 @@ export {
|
|
|
311
313
|
rpcQueryFeeGrantsIssued,
|
|
312
314
|
rpcQueryAuthzGrants,
|
|
313
315
|
rpcQueryProvider,
|
|
316
|
+
rpcGetTxByHash,
|
|
314
317
|
} from './chain/rpc.js';
|
|
315
318
|
|
|
316
319
|
// ─── Subscription Sharing (plan operator → user onboarding) ────────────────
|
|
@@ -323,6 +326,7 @@ export {
|
|
|
323
326
|
|
|
324
327
|
export {
|
|
325
328
|
querySubscriptionAllocations,
|
|
329
|
+
getTxByHash,
|
|
326
330
|
} from './chain/queries.js';
|
|
327
331
|
|
|
328
332
|
// ─── TypeScript Client (extends CosmJS SigningStargateClient) ───────────────
|
package/node-connect.js
CHANGED
|
@@ -1011,7 +1011,17 @@ export async function connectDirect(opts) {
|
|
|
1011
1011
|
if (!forceNewSession) {
|
|
1012
1012
|
progress(onProgress, logFn, 'session', 'Checking for existing session...');
|
|
1013
1013
|
checkAborted(signal);
|
|
1014
|
-
sessionId = await findExistingSession(lcd, account.address, opts.nodeAddress
|
|
1014
|
+
sessionId = await findExistingSession(lcd, account.address, opts.nodeAddress, {
|
|
1015
|
+
// Dedup: if multiple active sessions exist for this node (stale duplicates from
|
|
1016
|
+
// crashes or multi-client wallets), keep the highest-ID one. Silently cancel stale
|
|
1017
|
+
// lower-ID sessions before MsgStartSession — mirrors C# SessionManager dedup pattern.
|
|
1018
|
+
onStaleDuplicate: (staleId) => {
|
|
1019
|
+
logFn?.(`[connect] Cancelling stale duplicate session ${staleId} on ${opts.nodeAddress}...`);
|
|
1020
|
+
_endSessionOnChain(staleId, opts.mnemonic, opts.feeGranter || null).catch(e => {
|
|
1021
|
+
logFn?.(`[connect] Failed to cancel stale session ${staleId}: ${e.message}`);
|
|
1022
|
+
});
|
|
1023
|
+
},
|
|
1024
|
+
});
|
|
1015
1025
|
if (sessionId && isSessionPoisoned(String(sessionId))) {
|
|
1016
1026
|
progress(onProgress, logFn, 'session', `Session ${sessionId} previously failed — skipping`);
|
|
1017
1027
|
sessionId = null;
|
|
@@ -1460,8 +1470,10 @@ async function connectInternal(opts, paymentStrategy, retryStrategy, state = _de
|
|
|
1460
1470
|
{ nodeAddress: state.connection?.nodeAddress });
|
|
1461
1471
|
}
|
|
1462
1472
|
const prev = state.connection;
|
|
1463
|
-
|
|
1464
|
-
|
|
1473
|
+
// Hard disconnect: user is actively connecting to a different node,
|
|
1474
|
+
// so the old session should be settled and the deposit refunded.
|
|
1475
|
+
await disconnectStateAndEndSession(state);
|
|
1476
|
+
if (opts.log || defaultLog) (opts.log || defaultLog)(`[connect] Ended session on ${prev?.nodeAddress || 'previous node'} — connecting to new node`);
|
|
1465
1477
|
}
|
|
1466
1478
|
|
|
1467
1479
|
const onProgress = opts.onProgress || null;
|
|
@@ -2267,13 +2279,35 @@ function formatUptime(ms) {
|
|
|
2267
2279
|
}
|
|
2268
2280
|
|
|
2269
2281
|
// ─── Disconnect ──────────────────────────────────────────────────────────────
|
|
2282
|
+
//
|
|
2283
|
+
// TWO DISCONNECT PATHS — CHOOSE INTENT EXPLICITLY.
|
|
2284
|
+
//
|
|
2285
|
+
// Soft: disconnect() / disconnectState(state)
|
|
2286
|
+
// - Tears down the local tunnel (WireGuard/V2Ray) and cleans up system state.
|
|
2287
|
+
// - Leaves the on-chain session in status=1 (active).
|
|
2288
|
+
// - Next connectDirect() to the SAME node reuses the session via
|
|
2289
|
+
// findExistingSession — no new MsgStartSession TX, no new payment, bandwidth preserved.
|
|
2290
|
+
// - Use when: user is pausing, network changed, closing the app temporarily.
|
|
2291
|
+
//
|
|
2292
|
+
// Hard: disconnectAndEndSession() / disconnectStateAndEndSession(state)
|
|
2293
|
+
// - Tears down the tunnel AND broadcasts MsgCancelSession on chain.
|
|
2294
|
+
// - Session moves status=1 → settling → refund after ~2h settlement window.
|
|
2295
|
+
// - Use when: user is done with this node, switching nodes permanently,
|
|
2296
|
+
// or wants the bandwidth deposit back.
|
|
2297
|
+
//
|
|
2298
|
+
// Internal: _disconnectInternal(state, { endSession })
|
|
2299
|
+
// - Caller MUST pass endSession explicitly as true or false.
|
|
2300
|
+
// - No default — forces intentional choice at every callsite.
|
|
2270
2301
|
|
|
2271
2302
|
/**
|
|
2272
|
-
*
|
|
2273
|
-
*
|
|
2303
|
+
* Internal disconnect implementation. Caller must explicitly pass endSession.
|
|
2304
|
+
* @param {object} state - ConnectionState instance
|
|
2305
|
+
* @param {{ endSession: boolean }} opts
|
|
2306
|
+
* endSession: true → broadcast MsgCancelSession (hard disconnect)
|
|
2307
|
+
* endSession: false → preserve on-chain session for reuse (soft disconnect)
|
|
2308
|
+
* @private
|
|
2274
2309
|
*/
|
|
2275
|
-
|
|
2276
|
-
export async function disconnectState(state) {
|
|
2310
|
+
async function _disconnectInternal(state, { endSession }) {
|
|
2277
2311
|
// v30: Signal any running connectAuto() retry loop to abort, and release the
|
|
2278
2312
|
// connection lock so the user can reconnect after disconnect completes.
|
|
2279
2313
|
_abortConnect = true;
|
|
@@ -2299,11 +2333,18 @@ export async function disconnectState(state) {
|
|
|
2299
2333
|
state.wgTunnel = null;
|
|
2300
2334
|
}
|
|
2301
2335
|
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2336
|
+
if (endSession) {
|
|
2337
|
+
// Hard disconnect: broadcast MsgCancelSession — session settles and refunds deposit.
|
|
2338
|
+
if (prev?.sessionId && state._mnemonic) {
|
|
2339
|
+
_endSessionOnChain(prev.sessionId, state._mnemonic, state._feeGranter).catch(e => {
|
|
2340
|
+
console.warn(`[sentinel-sdk] Failed to end session ${prev.sessionId} on chain: ${e.message}`);
|
|
2341
|
+
});
|
|
2342
|
+
}
|
|
2343
|
+
} else {
|
|
2344
|
+
// Soft disconnect: leave session on chain in status=1 for reuse.
|
|
2345
|
+
if (prev?.sessionId) {
|
|
2346
|
+
console.log(`[sentinel-sdk] Session ${prev.sessionId} preserved on chain (status=1) for future reuse — no MsgCancelSession broadcast.`);
|
|
2347
|
+
}
|
|
2307
2348
|
}
|
|
2308
2349
|
} finally {
|
|
2309
2350
|
// ALWAYS clear connection state — even if teardown threw
|
|
@@ -2317,8 +2358,55 @@ export async function disconnectState(state) {
|
|
|
2317
2358
|
}
|
|
2318
2359
|
}
|
|
2319
2360
|
|
|
2361
|
+
/**
|
|
2362
|
+
* Soft disconnect — tear down the local tunnel, leave the on-chain session active.
|
|
2363
|
+
*
|
|
2364
|
+
* A subsequent connectDirect() to the SAME node will reuse the session via
|
|
2365
|
+
* findExistingSession — no new MsgStartSession TX, no new payment, remaining
|
|
2366
|
+
* bandwidth is preserved.
|
|
2367
|
+
*
|
|
2368
|
+
* Use when: user is pausing, network changed, or closing the app temporarily.
|
|
2369
|
+
* To settle the session on-chain and reclaim the unused deposit, use
|
|
2370
|
+
* disconnectAndEndSession() instead.
|
|
2371
|
+
*
|
|
2372
|
+
* @param {object} state - ConnectionState instance
|
|
2373
|
+
*/
|
|
2374
|
+
export async function disconnectState(state) {
|
|
2375
|
+
return _disconnectInternal(state, { endSession: false });
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
/**
|
|
2379
|
+
* Soft disconnect (default state) — tear down the tunnel, leave on-chain session active.
|
|
2380
|
+
*
|
|
2381
|
+
* @see disconnectState
|
|
2382
|
+
*/
|
|
2320
2383
|
export async function disconnect() {
|
|
2321
|
-
return
|
|
2384
|
+
return _disconnectInternal(_defaultState, { endSession: false });
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2387
|
+
/**
|
|
2388
|
+
* Hard disconnect — tear down the tunnel AND broadcast MsgCancelSession on chain.
|
|
2389
|
+
*
|
|
2390
|
+
* The session settles after the ~2h inactive_pending window. The node refunds
|
|
2391
|
+
* the unused portion of the bandwidth deposit (for peer-to-peer sessions).
|
|
2392
|
+
* For plan-based sessions, this stops metering against the plan allocation.
|
|
2393
|
+
*
|
|
2394
|
+
* Use when: user is done with this node (switching nodes permanently, ending
|
|
2395
|
+
* their session, or wants the deposit back).
|
|
2396
|
+
*
|
|
2397
|
+
* @param {object} state - ConnectionState instance
|
|
2398
|
+
*/
|
|
2399
|
+
export async function disconnectStateAndEndSession(state) {
|
|
2400
|
+
return _disconnectInternal(state, { endSession: true });
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
/**
|
|
2404
|
+
* Hard disconnect (default state) — tear down the tunnel AND broadcast MsgCancelSession.
|
|
2405
|
+
*
|
|
2406
|
+
* @see disconnectStateAndEndSession
|
|
2407
|
+
*/
|
|
2408
|
+
export async function disconnectAndEndSession() {
|
|
2409
|
+
return _disconnectInternal(_defaultState, { endSession: true });
|
|
2322
2410
|
}
|
|
2323
2411
|
|
|
2324
2412
|
// ─── Session End (on-chain cleanup) ──────────────────────────────────────────
|
package/operator.js
CHANGED
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blue-js-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Decentralized VPN SDK for the Sentinel P2P bandwidth network. WireGuard + V2Ray tunnels, Cosmos blockchain, 900+ nodes. Tested on Windows. macOS/Linux support included but untested.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"types": "types/index.d.ts",
|
|
8
8
|
"bin": {
|
|
9
|
-
"sentinel": "./cli/index.js"
|
|
10
|
-
"sentinel-ai": "./ai-path/cli.js"
|
|
9
|
+
"sentinel": "./cli/index.js"
|
|
11
10
|
},
|
|
12
11
|
"exports": {
|
|
13
12
|
".": {
|
|
@@ -16,7 +15,6 @@
|
|
|
16
15
|
},
|
|
17
16
|
"./consumer": "./consumer.js",
|
|
18
17
|
"./operator": "./operator.js",
|
|
19
|
-
"./ai-path": "./ai-path/index.js",
|
|
20
18
|
"./blue": {
|
|
21
19
|
"types": "./dist/index.d.ts",
|
|
22
20
|
"default": "./dist/index.js"
|
|
@@ -49,7 +47,6 @@
|
|
|
49
47
|
"errors/",
|
|
50
48
|
"examples/",
|
|
51
49
|
"docs/",
|
|
52
|
-
"ai-path/",
|
|
53
50
|
"bin/setup.js",
|
|
54
51
|
"dist/",
|
|
55
52
|
"src/",
|
package/types/index.d.ts
CHANGED
|
@@ -469,8 +469,8 @@ export function isMnemonicValid(mnemonic: string): boolean;
|
|
|
469
469
|
/** Get current P2P price in USD */
|
|
470
470
|
export function getDvpnPrice(): Promise<number>;
|
|
471
471
|
|
|
472
|
-
/** Find existing active session for wallet+node pair */
|
|
473
|
-
export function findExistingSession(lcdUrl: string, walletAddr: string, nodeAddr: string): Promise<bigint | null>;
|
|
472
|
+
/** Find existing active session for wallet+node pair. Deduplicates stale sessions via onStaleDuplicate callback. */
|
|
473
|
+
export function findExistingSession(lcdUrl: string, walletAddr: string, nodeAddr: string, opts?: { onStaleDuplicate?: (sessionId: bigint) => void }): Promise<bigint | null>;
|
|
474
474
|
|
|
475
475
|
/** Fetch active nodes from LCD with pagination */
|
|
476
476
|
export function fetchActiveNodes(lcdUrl: string, limit?: number, maxPages?: number): Promise<unknown[]>;
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
# Admin Elevation Guide — Sentinel AI Path
|
|
2
|
-
|
|
3
|
-
## Why Admin is Required
|
|
4
|
-
|
|
5
|
-
WireGuard tunnel operations require system-level access:
|
|
6
|
-
- **Windows:** Installing/removing WireGuard tunnel services (wireguard.exe /installtunnelservice)
|
|
7
|
-
- **macOS:** Creating utun interfaces (wg-quick up)
|
|
8
|
-
- **Linux:** Creating WireGuard interfaces (ip link add wg0)
|
|
9
|
-
|
|
10
|
-
Without admin, you can only use V2Ray nodes (~70% of the network). With admin, you access 100% of nodes including the faster, more reliable WireGuard nodes.
|
|
11
|
-
|
|
12
|
-
**The SDK checks admin BEFORE payment.** If you're not admin and select a WireGuard node, the SDK rejects the connection before any P2P tokens are spent. No money is wasted.
|
|
13
|
-
|
|
14
|
-
## Windows — Using run-admin.vbs
|
|
15
|
-
|
|
16
|
-
The `run-admin.vbs` script triggers a single UAC prompt, then runs your Node.js script with full Administrator privileges. One prompt per session.
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
# Setup (downloads V2Ray + installs WireGuard silently)
|
|
20
|
-
cscript run-admin.vbs setup.js
|
|
21
|
-
|
|
22
|
-
# Connect via CLI
|
|
23
|
-
cscript run-admin.vbs cli.js connect
|
|
24
|
-
|
|
25
|
-
# Run any custom script
|
|
26
|
-
cscript run-admin.vbs my-agent.mjs
|
|
27
|
-
|
|
28
|
-
# Test WireGuard specifically
|
|
29
|
-
cscript run-admin.vbs test-wireguard.mjs
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### How run-admin.vbs works
|
|
33
|
-
1. Calls `Shell.Application.ShellExecute` with verb `"runas"` → triggers UAC
|
|
34
|
-
2. Opens an elevated cmd.exe window
|
|
35
|
-
3. cd's to the script directory
|
|
36
|
-
4. Runs `node <your-script>`
|
|
37
|
-
5. Keeps the window open (so you can see output)
|
|
38
|
-
|
|
39
|
-
### For AI agents running unattended
|
|
40
|
-
If the AI agent runs as a Windows Service or scheduled task, configure it to run as a user with admin rights (e.g., SYSTEM or a dedicated admin account). No UAC prompt needed for services.
|
|
41
|
-
|
|
42
|
-
## macOS — Using sudo
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
sudo node setup.js # Install WireGuard via brew
|
|
46
|
-
sudo node cli.js connect # Connect with WireGuard access
|
|
47
|
-
sudo node my-agent.mjs # Run agent elevated
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
For unattended agents, add to sudoers:
|
|
51
|
-
```
|
|
52
|
-
agent-user ALL=(ALL) NOPASSWD: /usr/local/bin/node
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Linux — Using sudo
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
sudo node setup.js # Install wireguard-tools via apt/dnf
|
|
59
|
-
sudo node cli.js connect # Connect with WireGuard access
|
|
60
|
-
sudo node my-agent.mjs # Run agent elevated
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
For unattended agents in systemd:
|
|
64
|
-
```ini
|
|
65
|
-
[Service]
|
|
66
|
-
User=root
|
|
67
|
-
ExecStart=/usr/local/bin/node /path/to/my-agent.mjs
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Or use capabilities instead of full root:
|
|
71
|
-
```bash
|
|
72
|
-
sudo setcap cap_net_admin+ep $(which node)
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## V2Ray-Only Mode (No Admin Needed)
|
|
76
|
-
|
|
77
|
-
If admin is not available, the SDK automatically falls back to V2Ray nodes:
|
|
78
|
-
|
|
79
|
-
```js
|
|
80
|
-
const vpn = await connect({
|
|
81
|
-
mnemonic: process.env.MNEMONIC,
|
|
82
|
-
protocol: 'v2ray', // Explicitly request V2Ray only
|
|
83
|
-
});
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
V2Ray runs as a userspace SOCKS5 proxy — no system-level access needed. It connects to ~630 nodes (70% of the network). This is the recommended mode for:
|
|
87
|
-
- CI/CD pipelines
|
|
88
|
-
- Docker containers without --privileged
|
|
89
|
-
- Cloud VMs where root is restricted
|
|
90
|
-
- Development/testing
|
|
91
|
-
|
|
92
|
-
## Detection in Code
|
|
93
|
-
|
|
94
|
-
The SDK exports `IS_ADMIN` for checking:
|
|
95
|
-
|
|
96
|
-
```js
|
|
97
|
-
import { IS_ADMIN, WG_AVAILABLE } from 'sentinel-dvpn-sdk';
|
|
98
|
-
|
|
99
|
-
if (WG_AVAILABLE && IS_ADMIN) {
|
|
100
|
-
console.log('Full network access (WireGuard + V2Ray)');
|
|
101
|
-
} else if (WG_AVAILABLE && !IS_ADMIN) {
|
|
102
|
-
console.log('WireGuard installed but not admin — V2Ray only');
|
|
103
|
-
console.log('Run: cscript run-admin.vbs your-script.mjs');
|
|
104
|
-
} else {
|
|
105
|
-
console.log('V2Ray only (WireGuard not installed)');
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
The `getEnvironment()` function reports this:
|
|
110
|
-
```js
|
|
111
|
-
import { getEnvironment } from 'sentinel-ai-connect';
|
|
112
|
-
const env = getEnvironment();
|
|
113
|
-
// env.admin: true/false
|
|
114
|
-
// env.capabilities: ['v2ray', 'wireguard'] or ['v2ray', 'wireguard-needs-admin'] or ['v2ray']
|
|
115
|
-
// env.recommended: ['run as admin to use WireGuard nodes (faster, more reliable)']
|
|
116
|
-
```
|