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/cli.js
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// ─── Sentinel SDK CLI ───
|
|
4
|
+
//
|
|
5
|
+
// Command-line interface for common Sentinel operations.
|
|
6
|
+
// No GUI needed — scriptable, pipe-friendly, perfect for automation.
|
|
7
|
+
//
|
|
8
|
+
// Usage:
|
|
9
|
+
// node js-sdk/cli.js <command> [options]
|
|
10
|
+
//
|
|
11
|
+
// Examples:
|
|
12
|
+
// node js-sdk/cli.js balance
|
|
13
|
+
// node js-sdk/cli.js nodes --country Germany --limit 10
|
|
14
|
+
// node js-sdk/cli.js connect sentnode1abc...
|
|
15
|
+
// node js-sdk/cli.js plan-create --gb 10 --days 30 --price 1000000
|
|
16
|
+
// node js-sdk/cli.js grant-subscribers --plan 42
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
createWallet,
|
|
20
|
+
generateWallet,
|
|
21
|
+
getBalance,
|
|
22
|
+
isMnemonicValid,
|
|
23
|
+
createClient,
|
|
24
|
+
fetchActiveNodes,
|
|
25
|
+
getNodePrices,
|
|
26
|
+
getNetworkOverview,
|
|
27
|
+
filterNodes,
|
|
28
|
+
queryPlanNodes,
|
|
29
|
+
queryPlanSubscribers,
|
|
30
|
+
getPlanStats,
|
|
31
|
+
discoverPlans,
|
|
32
|
+
hasActiveSubscription,
|
|
33
|
+
querySubscriptions,
|
|
34
|
+
findExistingSession,
|
|
35
|
+
connectDirect,
|
|
36
|
+
connectAuto,
|
|
37
|
+
connectViaSubscription,
|
|
38
|
+
disconnect,
|
|
39
|
+
isConnected,
|
|
40
|
+
getStatus,
|
|
41
|
+
registerCleanupHandlers,
|
|
42
|
+
verifyDependencies,
|
|
43
|
+
formatDvpn,
|
|
44
|
+
shortAddress,
|
|
45
|
+
buildFeeGrantMsg,
|
|
46
|
+
buildRevokeFeeGrantMsg,
|
|
47
|
+
queryFeeGrants,
|
|
48
|
+
queryFeeGrantsIssued,
|
|
49
|
+
getExpiringGrants,
|
|
50
|
+
grantPlanSubscribers,
|
|
51
|
+
broadcastWithFeeGrant,
|
|
52
|
+
broadcast,
|
|
53
|
+
createSafeBroadcaster,
|
|
54
|
+
sentToSentprov,
|
|
55
|
+
sentToSentnode,
|
|
56
|
+
encodeMsgCreatePlan,
|
|
57
|
+
encodeMsgLinkNode,
|
|
58
|
+
encodeMsgUnlinkNode,
|
|
59
|
+
encodeMsgUpdatePlanStatus,
|
|
60
|
+
encodeMsgRegisterProvider,
|
|
61
|
+
encodeMsgUpdateProviderStatus,
|
|
62
|
+
encodeMsgStartLease,
|
|
63
|
+
encodeMsgEndLease,
|
|
64
|
+
encodeMsgStartSubscription,
|
|
65
|
+
LCD_ENDPOINTS,
|
|
66
|
+
DEFAULT_RPC,
|
|
67
|
+
DNS_PRESETS,
|
|
68
|
+
DEFAULT_DNS_PRESET,
|
|
69
|
+
DNS_FALLBACK_ORDER,
|
|
70
|
+
resolveDnsServers,
|
|
71
|
+
} from './index.js';
|
|
72
|
+
|
|
73
|
+
import { config } from 'dotenv';
|
|
74
|
+
config({ path: '.env' });
|
|
75
|
+
|
|
76
|
+
// ─── Helpers ───
|
|
77
|
+
|
|
78
|
+
const MNEMONIC = process.env.MNEMONIC;
|
|
79
|
+
const args = process.argv.slice(2);
|
|
80
|
+
const command = args[0];
|
|
81
|
+
|
|
82
|
+
function flag(name, defaultVal) {
|
|
83
|
+
const idx = args.indexOf(`--${name}`);
|
|
84
|
+
if (idx === -1) return defaultVal;
|
|
85
|
+
return args[idx + 1] || true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function die(msg) {
|
|
89
|
+
console.error(`Error: ${msg}`);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function getWallet() {
|
|
94
|
+
if (!MNEMONIC) die('MNEMONIC not set in .env');
|
|
95
|
+
const { wallet, account } = await createWallet(MNEMONIC);
|
|
96
|
+
return { wallet, account, address: account.address };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function getRpc() {
|
|
100
|
+
const { wallet, account } = await getWallet();
|
|
101
|
+
const client = await createClient(flag('rpc', DEFAULT_RPC), wallet);
|
|
102
|
+
return { client, wallet, account, address: account.address };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function json(obj) {
|
|
106
|
+
console.log(JSON.stringify(obj, (k, v) => typeof v === 'bigint' ? v.toString() : v, 2));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ─── Commands ───
|
|
110
|
+
|
|
111
|
+
const commands = {
|
|
112
|
+
|
|
113
|
+
async help() {
|
|
114
|
+
console.log(`
|
|
115
|
+
Sentinel SDK CLI — command-line tools for Sentinel dVPN
|
|
116
|
+
|
|
117
|
+
WALLET
|
|
118
|
+
balance Show wallet balance
|
|
119
|
+
generate Generate new mnemonic + address
|
|
120
|
+
address Show wallet address + provider address
|
|
121
|
+
|
|
122
|
+
NODES
|
|
123
|
+
nodes [--country X] [--limit N] List active nodes
|
|
124
|
+
node-prices <sentnode1...> Show node pricing
|
|
125
|
+
network Network overview (total nodes, by country)
|
|
126
|
+
|
|
127
|
+
PLANS
|
|
128
|
+
plans Discover plans on chain
|
|
129
|
+
plan-stats <planId> Plan statistics (subscribers, nodes, revenue)
|
|
130
|
+
plan-nodes <planId> List nodes in a plan
|
|
131
|
+
plan-subscribers <planId> List plan subscribers
|
|
132
|
+
plan-create --gb N --days N --price N Create a new plan
|
|
133
|
+
plan-activate <planId> Activate a plan
|
|
134
|
+
plan-link <planId> <sentnode1> Link a node to a plan
|
|
135
|
+
plan-unlink <planId> <sentnode1> Unlink a node from a plan
|
|
136
|
+
|
|
137
|
+
SUBSCRIPTIONS
|
|
138
|
+
subscriptions List your subscriptions
|
|
139
|
+
subscribe <planId> Subscribe to a plan
|
|
140
|
+
has-subscription <planId> Check if subscribed to a plan
|
|
141
|
+
|
|
142
|
+
SESSIONS
|
|
143
|
+
find-session <sentnode1...> Find existing session for a node
|
|
144
|
+
|
|
145
|
+
FEE GRANTS
|
|
146
|
+
grants-received List fee grants you've received
|
|
147
|
+
grants-issued List fee grants you've issued
|
|
148
|
+
grant <sent1...> [--amount N] Grant fee allowance to an address
|
|
149
|
+
grant-subscribers <planId> Batch grant all plan subscribers
|
|
150
|
+
expiring-grants [--days 7] List grants expiring soon
|
|
151
|
+
|
|
152
|
+
CONNECTION
|
|
153
|
+
connect <sentnode1...> [--gb N] [--dns X] Connect to a specific node
|
|
154
|
+
connect-auto [--country X] [--dns X] Auto-connect to best node
|
|
155
|
+
disconnect Disconnect VPN
|
|
156
|
+
status Show connection status
|
|
157
|
+
|
|
158
|
+
DNS
|
|
159
|
+
dns Show DNS presets and current resolution
|
|
160
|
+
dns --preset <name> Show resolved DNS for a preset
|
|
161
|
+
dns --custom <ip1,ip2> Show resolved DNS for custom IPs
|
|
162
|
+
|
|
163
|
+
SYSTEM
|
|
164
|
+
deps Check V2Ray + WireGuard availability
|
|
165
|
+
endpoints Test LCD endpoint health
|
|
166
|
+
|
|
167
|
+
Options:
|
|
168
|
+
--rpc <url> RPC endpoint (default: ${DEFAULT_RPC})
|
|
169
|
+
--lcd <url> LCD endpoint (default: ${LCD_ENDPOINTS[0].url || LCD_ENDPOINTS[0]})
|
|
170
|
+
--country <name> Filter by country
|
|
171
|
+
--limit <n> Limit results
|
|
172
|
+
--gb <n> Gigabytes (default: 1)
|
|
173
|
+
--days <n> Duration in days
|
|
174
|
+
--price <udvpn> Price in micro-denomination
|
|
175
|
+
--amount <udvpn> Fee grant amount in udvpn
|
|
176
|
+
--plan <id> Plan ID
|
|
177
|
+
--dns <preset> DNS preset: handshake (default), google, cloudflare, or custom IPs
|
|
178
|
+
|
|
179
|
+
Environment:
|
|
180
|
+
MNEMONIC BIP39 mnemonic phrase (in .env file)
|
|
181
|
+
`);
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
// ─── Wallet ───
|
|
185
|
+
|
|
186
|
+
async balance() {
|
|
187
|
+
const { client, address } = await getRpc();
|
|
188
|
+
const balance = await getBalance(client, address);
|
|
189
|
+
console.log(`Address: ${address}`);
|
|
190
|
+
console.log(`Balance: ${formatDvpn(balance.udvpn)} (${balance.udvpn} udvpn)`);
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
async generate() {
|
|
194
|
+
const { mnemonic, account } = await generateWallet();
|
|
195
|
+
console.log(`Mnemonic: ${mnemonic}`);
|
|
196
|
+
console.log(`Address: ${account.address}`);
|
|
197
|
+
console.log(`\nSave the mnemonic in your .env file as MNEMONIC="..."`);
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
async address() {
|
|
201
|
+
const { address } = await getWallet();
|
|
202
|
+
console.log(`Account: ${address}`);
|
|
203
|
+
console.log(`Provider: ${sentToSentprov(address)}`);
|
|
204
|
+
console.log(`Node: ${sentToSentnode(address)}`);
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
// ─── Nodes ───
|
|
208
|
+
|
|
209
|
+
async nodes() {
|
|
210
|
+
const country = flag('country', null);
|
|
211
|
+
const limit = parseInt(flag('limit', '20'));
|
|
212
|
+
let nodes = await fetchActiveNodes();
|
|
213
|
+
if (country) nodes = filterNodes(nodes, { country });
|
|
214
|
+
nodes = nodes.slice(0, limit);
|
|
215
|
+
console.log(`${nodes.length} nodes:`);
|
|
216
|
+
for (const n of nodes) {
|
|
217
|
+
const addr = shortAddress(n.address, 15, 6);
|
|
218
|
+
const url = n.remote_addrs?.[0] || n.remote_url || '?';
|
|
219
|
+
console.log(` ${addr} ${url} ${n.service_type === 2 ? 'WG' : 'V2'}`);
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
|
|
223
|
+
async 'node-prices'() {
|
|
224
|
+
const nodeAddr = args[1];
|
|
225
|
+
if (!nodeAddr) die('Usage: node-prices <sentnode1...>');
|
|
226
|
+
const prices = await getNodePrices(nodeAddr);
|
|
227
|
+
json(prices);
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
async network() {
|
|
231
|
+
const overview = await getNetworkOverview();
|
|
232
|
+
json(overview);
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
// ─── Plans ───
|
|
236
|
+
|
|
237
|
+
async plans() {
|
|
238
|
+
const plans = await discoverPlans();
|
|
239
|
+
console.log(`${plans.length} plans found:`);
|
|
240
|
+
for (const p of plans) {
|
|
241
|
+
console.log(` Plan ${p.id}: ${p.subscribers} subscribers, ${p.nodeCount} nodes`);
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
async 'plan-stats'() {
|
|
246
|
+
const planId = parseInt(args[1]);
|
|
247
|
+
if (!planId) die('Usage: plan-stats <planId>');
|
|
248
|
+
const { address } = await getWallet();
|
|
249
|
+
const stats = await getPlanStats(planId, address);
|
|
250
|
+
json(stats);
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
async 'plan-nodes'() {
|
|
254
|
+
const planId = parseInt(args[1]);
|
|
255
|
+
if (!planId) die('Usage: plan-nodes <planId>');
|
|
256
|
+
const nodes = await queryPlanNodes(planId);
|
|
257
|
+
console.log(`${nodes.length} nodes in plan ${planId}:`);
|
|
258
|
+
for (const n of nodes) {
|
|
259
|
+
console.log(` ${n.address} ${n.remote_addrs?.[0] || '?'}`);
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
async 'plan-subscribers'() {
|
|
264
|
+
const planId = parseInt(args[1]);
|
|
265
|
+
if (!planId) die('Usage: plan-subscribers <planId>');
|
|
266
|
+
const subs = await queryPlanSubscribers(planId);
|
|
267
|
+
console.log(`${subs.length} subscribers:`);
|
|
268
|
+
for (const s of subs) {
|
|
269
|
+
console.log(` ${s.address} status=${s.status}`);
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
async 'plan-create'() {
|
|
274
|
+
const gb = parseInt(flag('gb', '10'));
|
|
275
|
+
const days = parseInt(flag('days', '30'));
|
|
276
|
+
const price = flag('price', null);
|
|
277
|
+
if (!price) die('Usage: plan-create --gb 10 --days 30 --price 1000000');
|
|
278
|
+
const { client, address } = await getRpc();
|
|
279
|
+
const provAddr = sentToSentprov(address);
|
|
280
|
+
const msg = encodeMsgCreatePlan({
|
|
281
|
+
from: provAddr,
|
|
282
|
+
bytes: String(BigInt(gb) * 1000000000n),
|
|
283
|
+
duration: days * 86400,
|
|
284
|
+
prices: [{ denom: 'udvpn', base_value: '1', quote_value: price }],
|
|
285
|
+
});
|
|
286
|
+
const result = await broadcast(client, address, [{ typeUrl: '/sentinel.plan.v3.MsgCreatePlanRequest', value: msg }]);
|
|
287
|
+
json({ txHash: result.transactionHash, code: result.code });
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
async 'plan-activate'() {
|
|
291
|
+
const planId = parseInt(args[1]);
|
|
292
|
+
if (!planId) die('Usage: plan-activate <planId>');
|
|
293
|
+
const { client, address } = await getRpc();
|
|
294
|
+
const provAddr = sentToSentprov(address);
|
|
295
|
+
const msg = encodeMsgUpdatePlanStatus({ from: provAddr, id: planId, status: 1 });
|
|
296
|
+
const result = await broadcast(client, address, [{ typeUrl: '/sentinel.plan.v3.MsgUpdatePlanStatusRequest', value: msg }]);
|
|
297
|
+
json({ txHash: result.transactionHash, code: result.code });
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
// ─── Subscriptions ───
|
|
301
|
+
|
|
302
|
+
async subscriptions() {
|
|
303
|
+
const { address } = await getWallet();
|
|
304
|
+
const subs = await querySubscriptions(LCD_ENDPOINTS[0]?.url || LCD_ENDPOINTS[0], address);
|
|
305
|
+
json(subs);
|
|
306
|
+
},
|
|
307
|
+
|
|
308
|
+
async subscribe() {
|
|
309
|
+
const planId = parseInt(args[1]);
|
|
310
|
+
if (!planId) die('Usage: subscribe <planId>');
|
|
311
|
+
const { client, address } = await getRpc();
|
|
312
|
+
const msg = encodeMsgStartSubscription({ from: address, id: planId, denom: 'udvpn' });
|
|
313
|
+
const result = await broadcast(client, address, [{ typeUrl: '/sentinel.subscription.v3.MsgStartRequest', value: msg }]);
|
|
314
|
+
json({ txHash: result.transactionHash, code: result.code });
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
async 'has-subscription'() {
|
|
318
|
+
const planId = parseInt(args[1]);
|
|
319
|
+
if (!planId) die('Usage: has-subscription <planId>');
|
|
320
|
+
const { address } = await getWallet();
|
|
321
|
+
const has = await hasActiveSubscription(address, planId);
|
|
322
|
+
console.log(has ? 'Yes — active subscription exists' : 'No — not subscribed');
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
// ─── Sessions ───
|
|
326
|
+
|
|
327
|
+
async 'find-session'() {
|
|
328
|
+
const nodeAddr = args[1];
|
|
329
|
+
if (!nodeAddr) die('Usage: find-session <sentnode1...>');
|
|
330
|
+
const { address } = await getWallet();
|
|
331
|
+
const sessionId = await findExistingSession(LCD_ENDPOINTS[0]?.url || LCD_ENDPOINTS[0], address, nodeAddr);
|
|
332
|
+
console.log(sessionId ? `Session: ${sessionId}` : 'No active session found');
|
|
333
|
+
},
|
|
334
|
+
|
|
335
|
+
// ─── Fee Grants ───
|
|
336
|
+
|
|
337
|
+
async 'grants-received'() {
|
|
338
|
+
const { address } = await getWallet();
|
|
339
|
+
const grants = await queryFeeGrants(LCD_ENDPOINTS[0]?.url || LCD_ENDPOINTS[0], address);
|
|
340
|
+
json(grants);
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
async 'grants-issued'() {
|
|
344
|
+
const { address } = await getWallet();
|
|
345
|
+
const grants = await queryFeeGrantsIssued(LCD_ENDPOINTS[0]?.url || LCD_ENDPOINTS[0], address);
|
|
346
|
+
json(grants);
|
|
347
|
+
},
|
|
348
|
+
|
|
349
|
+
async 'grant-subscribers'() {
|
|
350
|
+
const planId = parseInt(flag('plan', args[1]));
|
|
351
|
+
if (!planId) die('Usage: grant-subscribers <planId>');
|
|
352
|
+
const { address } = await getWallet();
|
|
353
|
+
const result = await grantPlanSubscribers(planId, {
|
|
354
|
+
granterAddress: address,
|
|
355
|
+
lcdUrl: LCD_ENDPOINTS[0]?.url || LCD_ENDPOINTS[0],
|
|
356
|
+
});
|
|
357
|
+
json(result);
|
|
358
|
+
},
|
|
359
|
+
|
|
360
|
+
async 'expiring-grants'() {
|
|
361
|
+
const days = parseInt(flag('days', '7'));
|
|
362
|
+
const { address } = await getWallet();
|
|
363
|
+
const expiring = await getExpiringGrants(
|
|
364
|
+
LCD_ENDPOINTS[0]?.url || LCD_ENDPOINTS[0],
|
|
365
|
+
address, days, 'granter',
|
|
366
|
+
);
|
|
367
|
+
json(expiring);
|
|
368
|
+
},
|
|
369
|
+
|
|
370
|
+
// ─── Connection ───
|
|
371
|
+
|
|
372
|
+
async connect() {
|
|
373
|
+
registerCleanupHandlers();
|
|
374
|
+
const nodeAddr = args[1];
|
|
375
|
+
if (!nodeAddr) die('Usage: connect <sentnode1...>');
|
|
376
|
+
const gb = parseInt(flag('gb', '1'));
|
|
377
|
+
const dns = flag('dns', undefined);
|
|
378
|
+
const result = await connectDirect({
|
|
379
|
+
mnemonic: MNEMONIC,
|
|
380
|
+
nodeAddress: nodeAddr,
|
|
381
|
+
gigabytes: gb,
|
|
382
|
+
dns,
|
|
383
|
+
onProgress: (step, detail) => console.log(`[${step}] ${detail}`),
|
|
384
|
+
});
|
|
385
|
+
json(result);
|
|
386
|
+
console.log(`\nDNS: ${resolveDnsServers(dns)}`);
|
|
387
|
+
console.log('VPN connected. Press Ctrl+C to disconnect.');
|
|
388
|
+
await new Promise(() => {}); // Keep alive
|
|
389
|
+
},
|
|
390
|
+
|
|
391
|
+
async 'connect-auto'() {
|
|
392
|
+
registerCleanupHandlers();
|
|
393
|
+
const country = flag('country', undefined);
|
|
394
|
+
const dns = flag('dns', undefined);
|
|
395
|
+
const result = await connectAuto({
|
|
396
|
+
mnemonic: MNEMONIC,
|
|
397
|
+
countries: country ? [country] : undefined,
|
|
398
|
+
dns,
|
|
399
|
+
onProgress: (step, detail) => console.log(`[${step}] ${detail}`),
|
|
400
|
+
});
|
|
401
|
+
json(result);
|
|
402
|
+
console.log(`\nDNS: ${resolveDnsServers(dns)}`);
|
|
403
|
+
console.log('VPN connected. Press Ctrl+C to disconnect.');
|
|
404
|
+
await new Promise(() => {});
|
|
405
|
+
},
|
|
406
|
+
|
|
407
|
+
// ─── DNS ───
|
|
408
|
+
|
|
409
|
+
async dns() {
|
|
410
|
+
const preset = flag('preset', undefined);
|
|
411
|
+
const custom = flag('custom', undefined);
|
|
412
|
+
|
|
413
|
+
if (custom) {
|
|
414
|
+
const ips = custom.split(',').map(s => s.trim());
|
|
415
|
+
console.log(`Custom DNS: ${ips.join(', ')}`);
|
|
416
|
+
console.log(`Resolved (with fallbacks): ${resolveDnsServers(ips)}`);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (preset) {
|
|
421
|
+
const p = DNS_PRESETS[preset.toLowerCase()];
|
|
422
|
+
if (!p) die(`Unknown preset: ${preset}. Available: ${Object.keys(DNS_PRESETS).join(', ')}`);
|
|
423
|
+
console.log(`Preset: ${p.name}`);
|
|
424
|
+
console.log(`Servers: ${p.servers.join(', ')}`);
|
|
425
|
+
console.log(`Resolved (with fallbacks): ${resolveDnsServers(preset)}`);
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Show all presets
|
|
430
|
+
console.log('DNS Presets:');
|
|
431
|
+
console.log(` Default: ${DEFAULT_DNS_PRESET}`);
|
|
432
|
+
console.log(` Fallback order: ${DNS_FALLBACK_ORDER.join(' → ')}\n`);
|
|
433
|
+
for (const [key, p] of Object.entries(DNS_PRESETS)) {
|
|
434
|
+
const isDefault = key === DEFAULT_DNS_PRESET ? ' (default)' : '';
|
|
435
|
+
console.log(` ${key}${isDefault}`);
|
|
436
|
+
console.log(` ${p.description}`);
|
|
437
|
+
console.log(` Servers: ${p.servers.join(', ')}`);
|
|
438
|
+
console.log(` With fallbacks: ${resolveDnsServers(key)}`);
|
|
439
|
+
console.log();
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
|
|
443
|
+
async disconnect() {
|
|
444
|
+
await disconnect();
|
|
445
|
+
console.log('Disconnected.');
|
|
446
|
+
},
|
|
447
|
+
|
|
448
|
+
async status() {
|
|
449
|
+
if (isConnected()) {
|
|
450
|
+
json(getStatus());
|
|
451
|
+
} else {
|
|
452
|
+
console.log('Not connected.');
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
|
|
456
|
+
// ─── System ───
|
|
457
|
+
|
|
458
|
+
async deps() {
|
|
459
|
+
const deps = verifyDependencies();
|
|
460
|
+
json(deps);
|
|
461
|
+
},
|
|
462
|
+
|
|
463
|
+
async endpoints() {
|
|
464
|
+
const endpoints = LCD_ENDPOINTS.map(e => typeof e === 'string' ? e : e.url);
|
|
465
|
+
for (const url of endpoints) {
|
|
466
|
+
const start = Date.now();
|
|
467
|
+
try {
|
|
468
|
+
const res = await fetch(`${url}/cosmos/base/tendermint/v1beta1/node_info`, {
|
|
469
|
+
signal: AbortSignal.timeout(5000),
|
|
470
|
+
});
|
|
471
|
+
const ms = Date.now() - start;
|
|
472
|
+
console.log(` ${res.ok ? 'OK' : 'ERR'} ${ms}ms ${url}`);
|
|
473
|
+
} catch {
|
|
474
|
+
console.log(` FAIL ${url}`);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
// ─── Run ───
|
|
481
|
+
|
|
482
|
+
if (!command || command === 'help' || command === '--help' || command === '-h') {
|
|
483
|
+
commands.help();
|
|
484
|
+
} else if (commands[command]) {
|
|
485
|
+
commands[command]().catch(err => {
|
|
486
|
+
console.error(`Error: ${err.message}`);
|
|
487
|
+
process.exit(1);
|
|
488
|
+
});
|
|
489
|
+
} else {
|
|
490
|
+
die(`Unknown command: ${command}. Run with --help for usage.`);
|
|
491
|
+
}
|