blue-js-sdk 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/CHANGELOG.md +446 -0
  2. package/LICENSE +21 -0
  3. package/README.md +75 -0
  4. package/ai-path/ADMIN-ELEVATION.md +116 -0
  5. package/ai-path/AI-MANIFESTO.md +185 -0
  6. package/ai-path/BREAKING.md +74 -0
  7. package/ai-path/CHECKLIST.md +619 -0
  8. package/ai-path/CONNECTION-STEPS.md +724 -0
  9. package/ai-path/DECISION-TREE.md +378 -0
  10. package/ai-path/DEPENDENCIES.md +459 -0
  11. package/ai-path/E2E-FLOW.md +1555 -0
  12. package/ai-path/FAILURES.md +403 -0
  13. package/ai-path/GUIDE.md +1217 -0
  14. package/ai-path/README.md +558 -0
  15. package/ai-path/SPLIT-TUNNEL.md +266 -0
  16. package/ai-path/cli.js +535 -0
  17. package/ai-path/connect.js +884 -0
  18. package/ai-path/discover.js +178 -0
  19. package/ai-path/environment.js +266 -0
  20. package/ai-path/errors.js +86 -0
  21. package/ai-path/examples/autonomous-agent.mjs +220 -0
  22. package/ai-path/examples/multi-region.mjs +174 -0
  23. package/ai-path/examples/one-shot.mjs +31 -0
  24. package/ai-path/index.js +60 -0
  25. package/ai-path/pricing.js +136 -0
  26. package/ai-path/recommend.js +413 -0
  27. package/ai-path/run-admin.vbs +25 -0
  28. package/ai-path/setup.js +291 -0
  29. package/ai-path/wallet.js +137 -0
  30. package/app-helpers.js +363 -0
  31. package/app-settings.js +95 -0
  32. package/app-types.js +267 -0
  33. package/audit.js +847 -0
  34. package/batch.js +293 -0
  35. package/bin/setup.js +376 -0
  36. package/chain/authz.js +109 -0
  37. package/chain/broadcast.js +472 -0
  38. package/chain/client.js +160 -0
  39. package/chain/fee-grants.js +305 -0
  40. package/chain/index.js +891 -0
  41. package/chain/lcd.js +313 -0
  42. package/chain/queries.js +547 -0
  43. package/chain/rpc.js +408 -0
  44. package/chain/wallet.js +141 -0
  45. package/cli/config.js +143 -0
  46. package/cli/index.js +463 -0
  47. package/cli/output.js +182 -0
  48. package/cli.js +491 -0
  49. package/client/index.js +251 -0
  50. package/client.js +271 -0
  51. package/config/index.js +255 -0
  52. package/connection/connect.js +849 -0
  53. package/connection/disconnect.js +180 -0
  54. package/connection/discovery.js +321 -0
  55. package/connection/index.js +76 -0
  56. package/connection/proxy.js +148 -0
  57. package/connection/resilience.js +428 -0
  58. package/connection/security.js +232 -0
  59. package/connection/state.js +369 -0
  60. package/connection/tunnel.js +691 -0
  61. package/consumer.js +132 -0
  62. package/cosmjs-setup.js +1884 -0
  63. package/defaults.js +366 -0
  64. package/disk-cache.js +107 -0
  65. package/dist/client.d.ts +108 -0
  66. package/dist/client.d.ts.map +1 -0
  67. package/dist/client.js +400 -0
  68. package/dist/client.js.map +1 -0
  69. package/dist/index.d.ts +8 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/dist/index.js +8 -0
  72. package/dist/index.js.map +1 -0
  73. package/errors/index.js +112 -0
  74. package/errors.js +218 -0
  75. package/examples/README.md +64 -0
  76. package/examples/connect-direct.mjs +106 -0
  77. package/examples/connect-plan.mjs +125 -0
  78. package/examples/error-handling.mjs +109 -0
  79. package/examples/query-nodes.mjs +94 -0
  80. package/examples/wallet-basics.mjs +61 -0
  81. package/generated/amino/amino.ts +9 -0
  82. package/generated/cosmos/base/v1beta1/coin.ts +365 -0
  83. package/generated/cosmos_proto/cosmos.ts +323 -0
  84. package/generated/gogoproto/gogo.ts +9 -0
  85. package/generated/google/protobuf/descriptor.ts +7601 -0
  86. package/generated/google/protobuf/duration.ts +208 -0
  87. package/generated/google/protobuf/timestamp.ts +238 -0
  88. package/generated/sentinel/lease/v1/events.ts +924 -0
  89. package/generated/sentinel/lease/v1/lease.ts +292 -0
  90. package/generated/sentinel/lease/v1/msg.ts +949 -0
  91. package/generated/sentinel/lease/v1/params.ts +164 -0
  92. package/generated/sentinel/node/v3/events.ts +881 -0
  93. package/generated/sentinel/node/v3/msg.ts +1002 -0
  94. package/generated/sentinel/node/v3/node.ts +263 -0
  95. package/generated/sentinel/node/v3/params.ts +183 -0
  96. package/generated/sentinel/plan/v3/events.ts +675 -0
  97. package/generated/sentinel/plan/v3/msg.ts +1191 -0
  98. package/generated/sentinel/plan/v3/plan.ts +283 -0
  99. package/generated/sentinel/provider/v2/events.ts +171 -0
  100. package/generated/sentinel/provider/v2/msg.ts +480 -0
  101. package/generated/sentinel/provider/v2/params.ts +131 -0
  102. package/generated/sentinel/provider/v2/provider.ts +246 -0
  103. package/generated/sentinel/session/v3/events.ts +480 -0
  104. package/generated/sentinel/session/v3/msg.ts +616 -0
  105. package/generated/sentinel/session/v3/params.ts +260 -0
  106. package/generated/sentinel/session/v3/proof.ts +180 -0
  107. package/generated/sentinel/session/v3/session.ts +384 -0
  108. package/generated/sentinel/subscription/v3/events.ts +1181 -0
  109. package/generated/sentinel/subscription/v3/msg.ts +1305 -0
  110. package/generated/sentinel/subscription/v3/params.ts +167 -0
  111. package/generated/sentinel/subscription/v3/subscription.ts +315 -0
  112. package/generated/sentinel/types/v1/bandwidth.ts +124 -0
  113. package/generated/sentinel/types/v1/price.ts +149 -0
  114. package/generated/sentinel/types/v1/renewal.ts +87 -0
  115. package/generated/sentinel/types/v1/status.ts +54 -0
  116. package/generated/typeRegistry.ts +27 -0
  117. package/index.js +486 -0
  118. package/node-connect.js +3015 -0
  119. package/operator.js +134 -0
  120. package/package.json +113 -0
  121. package/plan-operations.js +199 -0
  122. package/preflight.js +352 -0
  123. package/pricing/index.js +262 -0
  124. package/proto/amino/amino.proto +84 -0
  125. package/proto/cosmos/base/v1beta1/coin.proto +61 -0
  126. package/proto/cosmos_proto/cosmos.proto +112 -0
  127. package/proto/gogoproto/gogo.proto +145 -0
  128. package/proto/google/api/annotations.proto +31 -0
  129. package/proto/google/api/http.proto +370 -0
  130. package/proto/google/protobuf/any.proto +106 -0
  131. package/proto/google/protobuf/duration.proto +115 -0
  132. package/proto/google/protobuf/timestamp.proto +145 -0
  133. package/proto/sentinel/lease/v1/events.proto +52 -0
  134. package/proto/sentinel/lease/v1/genesis.proto +15 -0
  135. package/proto/sentinel/lease/v1/lease.proto +25 -0
  136. package/proto/sentinel/lease/v1/msg.proto +62 -0
  137. package/proto/sentinel/lease/v1/params.proto +17 -0
  138. package/proto/sentinel/node/v3/events.proto +50 -0
  139. package/proto/sentinel/node/v3/genesis.proto +15 -0
  140. package/proto/sentinel/node/v3/msg.proto +63 -0
  141. package/proto/sentinel/node/v3/node.proto +27 -0
  142. package/proto/sentinel/node/v3/params.proto +21 -0
  143. package/proto/sentinel/node/v3/querier.proto +63 -0
  144. package/proto/sentinel/plan/v3/events.proto +41 -0
  145. package/proto/sentinel/plan/v3/genesis.proto +21 -0
  146. package/proto/sentinel/plan/v3/msg.proto +83 -0
  147. package/proto/sentinel/plan/v3/plan.proto +32 -0
  148. package/proto/sentinel/plan/v3/querier.proto +53 -0
  149. package/proto/sentinel/provider/v2/events.proto +16 -0
  150. package/proto/sentinel/provider/v2/genesis.proto +15 -0
  151. package/proto/sentinel/provider/v2/msg.proto +35 -0
  152. package/proto/sentinel/provider/v2/params.proto +17 -0
  153. package/proto/sentinel/provider/v2/provider.proto +24 -0
  154. package/proto/sentinel/provider/v3/genesis.proto +15 -0
  155. package/proto/sentinel/provider/v3/params.proto +13 -0
  156. package/proto/sentinel/session/v3/events.proto +30 -0
  157. package/proto/sentinel/session/v3/genesis.proto +15 -0
  158. package/proto/sentinel/session/v3/msg.proto +50 -0
  159. package/proto/sentinel/session/v3/params.proto +25 -0
  160. package/proto/sentinel/session/v3/proof.proto +25 -0
  161. package/proto/sentinel/session/v3/querier.proto +100 -0
  162. package/proto/sentinel/session/v3/session.proto +50 -0
  163. package/proto/sentinel/subscription/v2/allocation.proto +21 -0
  164. package/proto/sentinel/subscription/v2/payout.proto +22 -0
  165. package/proto/sentinel/subscription/v3/events.proto +65 -0
  166. package/proto/sentinel/subscription/v3/genesis.proto +17 -0
  167. package/proto/sentinel/subscription/v3/msg.proto +83 -0
  168. package/proto/sentinel/subscription/v3/params.proto +21 -0
  169. package/proto/sentinel/subscription/v3/subscription.proto +33 -0
  170. package/proto/sentinel/types/v1/bandwidth.proto +19 -0
  171. package/proto/sentinel/types/v1/price.proto +21 -0
  172. package/proto/sentinel/types/v1/renewal.proto +21 -0
  173. package/proto/sentinel/types/v1/status.proto +16 -0
  174. package/protocol/encoding.js +341 -0
  175. package/protocol/events.js +361 -0
  176. package/protocol/handshake.js +297 -0
  177. package/protocol/index.js +15 -0
  178. package/protocol/messages.js +346 -0
  179. package/protocol/plans.js +199 -0
  180. package/protocol/v2ray.js +268 -0
  181. package/protocol/v3.js +723 -0
  182. package/protocol/wireguard.js +125 -0
  183. package/security/index.js +132 -0
  184. package/session-manager.js +329 -0
  185. package/session-tracker.js +80 -0
  186. package/setup.js +376 -0
  187. package/speedtest/index.js +528 -0
  188. package/speedtest.js +567 -0
  189. package/src/client.ts +502 -0
  190. package/src/index.ts +20 -0
  191. package/state/index.js +347 -0
  192. package/state.js +516 -0
  193. package/test-all-chain-ops.js +493 -0
  194. package/test-all-logic.js +199 -0
  195. package/test-all-msg-types.js +292 -0
  196. package/test-every-connection.js +208 -0
  197. package/test-feegrant-connect.js +98 -0
  198. package/test-logic.js +148 -0
  199. package/test-mainnet.js +176 -0
  200. package/test-plan-lifecycle.js +335 -0
  201. package/tls-trust.js +132 -0
  202. package/tsconfig.build.json +20 -0
  203. package/tsconfig.json +34 -0
  204. package/types/chain.d.ts +746 -0
  205. package/types/connection.d.ts +425 -0
  206. package/types/errors.d.ts +174 -0
  207. package/types/index.d.ts +1380 -0
  208. package/types/nodes.d.ts +187 -0
  209. package/types/pricing.d.ts +156 -0
  210. package/types/protocol.d.ts +332 -0
  211. package/types/session.d.ts +236 -0
  212. package/types/settings.d.ts +192 -0
  213. package/v3protocol.js +1053 -0
  214. package/wallet/index.js +153 -0
  215. package/wireguard.js +307 -0
@@ -0,0 +1,291 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Sentinel AI Connect — Auto-Setup Script
4
+ *
5
+ * Runs on postinstall or manually via: node setup.js
6
+ *
7
+ * Checks:
8
+ * 1. Node.js version >= 20
9
+ * 2. V2Ray binary (local bin/, parent SDK bin/, system PATH)
10
+ * 3. WireGuard installation (optional)
11
+ * 4. .env with MNEMONIC
12
+ *
13
+ * Delegates binary downloads to the parent SDK's setup.js when needed.
14
+ */
15
+
16
+ import { existsSync, readFileSync, copyFileSync } from 'fs';
17
+ import { execSync } from 'child_process';
18
+ import path from 'path';
19
+ import { fileURLToPath } from 'url';
20
+
21
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
22
+ const PARENT_SDK = path.resolve(__dirname, '..');
23
+
24
+ // ─── Status Tracking ────────────────────────────────────────────────────────
25
+
26
+ const status = {
27
+ node: { ok: false, detail: '' },
28
+ v2ray: { ok: false, detail: '' },
29
+ wireguard: { ok: false, detail: '' },
30
+ wallet: { ok: false, detail: '' },
31
+ };
32
+
33
+ // ─── Node.js Version Check ──────────────────────────────────────────────────
34
+
35
+ function checkNodeVersion() {
36
+ const major = parseInt(process.versions.node.split('.')[0], 10);
37
+ if (major >= 20) {
38
+ status.node = { ok: true, detail: `v${process.versions.node}` };
39
+ } else {
40
+ status.node = { ok: false, detail: `v${process.versions.node} (need >= 20)` };
41
+ }
42
+ }
43
+
44
+ // ─── V2Ray Binary Check ────────────────────────────────────────────────────
45
+
46
+ function findV2Ray() {
47
+ const binary = process.platform === 'win32' ? 'v2ray.exe' : 'v2ray';
48
+
49
+ // Search paths in priority order
50
+ const searchPaths = [
51
+ path.join(__dirname, 'bin', binary),
52
+ path.join(PARENT_SDK, 'bin', binary),
53
+ ];
54
+
55
+ // System paths
56
+ if (process.platform === 'win32') {
57
+ searchPaths.push('C:\\Program Files\\V2Ray\\v2ray.exe');
58
+ searchPaths.push('C:\\Program Files (x86)\\V2Ray\\v2ray.exe');
59
+ } else {
60
+ searchPaths.push('/usr/local/bin/v2ray');
61
+ searchPaths.push('/usr/bin/v2ray');
62
+ }
63
+
64
+ for (const p of searchPaths) {
65
+ if (existsSync(p)) {
66
+ status.v2ray = { ok: true, detail: `found at ${p}` };
67
+ return p;
68
+ }
69
+ }
70
+
71
+ // Check system PATH
72
+ try {
73
+ const cmd = process.platform === 'win32' ? 'where v2ray.exe' : 'which v2ray';
74
+ const result = execSync(cmd, { stdio: 'pipe', encoding: 'utf-8' }).trim();
75
+ if (result) {
76
+ status.v2ray = { ok: true, detail: `found at ${result.split('\n')[0]}` };
77
+ return result.split('\n')[0];
78
+ }
79
+ } catch {
80
+ // Not in PATH
81
+ }
82
+
83
+ status.v2ray = { ok: false, detail: 'not found' };
84
+ return null;
85
+ }
86
+
87
+ // ─── V2Ray Setup via Parent SDK ─────────────────────────────────────────────
88
+
89
+ async function setupV2Ray() {
90
+ const parentSetup = path.join(PARENT_SDK, 'setup.js');
91
+ if (!existsSync(parentSetup)) {
92
+ status.v2ray = { ok: false, detail: 'not found — parent SDK setup.js missing' };
93
+ return;
94
+ }
95
+
96
+ console.log('[setup] Downloading V2Ray via parent SDK...');
97
+ try {
98
+ // Windows ESM requires file:// URLs for absolute paths — raw C:\ paths fail
99
+ const { pathToFileURL } = await import('url');
100
+ const mod = await import(pathToFileURL(parentSetup).href);
101
+ // Parent setup.js runs on import (top-level await) or exports a function
102
+ if (typeof mod.default === 'function') {
103
+ await mod.default();
104
+ } else if (typeof mod.setup === 'function') {
105
+ await mod.setup();
106
+ }
107
+ // Re-check after download
108
+ findV2Ray();
109
+ } catch (err) {
110
+ status.v2ray = { ok: false, detail: `download failed — ${err.message}` };
111
+ }
112
+ }
113
+
114
+ // ─── WireGuard Check + Auto-Install ─────────────────────────────────────────
115
+
116
+ const WG_VERSION = '0.5.3';
117
+ const WG_MSI_URLS = {
118
+ 'win32-x64': `https://download.wireguard.com/windows-client/wireguard-amd64-${WG_VERSION}.msi`,
119
+ 'win32-arm64': `https://download.wireguard.com/windows-client/wireguard-arm64-${WG_VERSION}.msi`,
120
+ 'win32-ia32': `https://download.wireguard.com/windows-client/wireguard-x86-${WG_VERSION}.msi`,
121
+ };
122
+
123
+ function findWireGuard() {
124
+ const wgPaths = process.platform === 'win32'
125
+ ? ['C:\\Program Files\\WireGuard\\wireguard.exe', 'C:\\Program Files (x86)\\WireGuard\\wireguard.exe']
126
+ : ['/usr/bin/wg', '/usr/local/bin/wg', '/opt/homebrew/bin/wg'];
127
+
128
+ for (const p of wgPaths) {
129
+ if (existsSync(p)) return p;
130
+ }
131
+
132
+ try {
133
+ const cmd = process.platform === 'win32' ? 'where wireguard.exe' : 'which wg';
134
+ const result = execSync(cmd, { stdio: 'pipe', encoding: 'utf-8' }).trim();
135
+ if (result) return result.split('\n')[0];
136
+ } catch { /* not in PATH */ }
137
+
138
+ return null;
139
+ }
140
+
141
+ function isAdmin() {
142
+ if (process.platform === 'win32') {
143
+ try { execSync('net session', { stdio: 'pipe' }); return true; } catch {
144
+ try { execSync('fsutil dirty query C:', { stdio: 'pipe' }); return true; } catch { return false; }
145
+ }
146
+ }
147
+ return process.getuid?.() === 0;
148
+ }
149
+
150
+ async function checkWireGuard() {
151
+ const existing = findWireGuard();
152
+ if (existing) {
153
+ status.wireguard = { ok: true, detail: `found at ${existing}` };
154
+ return;
155
+ }
156
+
157
+ // Delegate to parent SDK's setup.js which has full auto-install logic
158
+ // (downloads MSI, silent installs, handles macOS brew, Linux apt/dnf)
159
+ const parentSetup = path.resolve(__dirname, '..', 'bin', 'setup.js');
160
+ if (existsSync(parentSetup)) {
161
+ console.log('[setup] WireGuard not found — attempting auto-install via SDK...');
162
+ try {
163
+ execSync(`node "${parentSetup}"`, { stdio: 'inherit', timeout: 180000 });
164
+ // Re-check after parent setup
165
+ const installed = findWireGuard();
166
+ if (installed) {
167
+ status.wireguard = { ok: true, detail: `auto-installed at ${installed}` };
168
+ return;
169
+ }
170
+ } catch (err) {
171
+ console.log(`[setup] WireGuard auto-install via SDK failed: ${err.message}`);
172
+ }
173
+ }
174
+
175
+ // Provide manual install URLs per platform
176
+ const platform = `${process.platform}-${process.arch}`;
177
+ const msiUrl = WG_MSI_URLS[platform];
178
+ if (process.platform === 'win32' && msiUrl) {
179
+ status.wireguard = {
180
+ ok: false,
181
+ detail: `not installed — run setup as admin for auto-install, or download: ${msiUrl}`,
182
+ };
183
+ } else if (process.platform === 'darwin') {
184
+ status.wireguard = { ok: false, detail: 'not installed — run: brew install wireguard-tools' };
185
+ } else if (process.platform === 'linux') {
186
+ status.wireguard = { ok: false, detail: 'not installed — run: sudo apt install wireguard-tools' };
187
+ } else {
188
+ status.wireguard = { ok: false, detail: 'not installed (optional — V2Ray nodes work without it)' };
189
+ }
190
+ }
191
+
192
+ // ─── Wallet / .env Check ───────────────────────────────────────────────────
193
+
194
+ function checkWallet() {
195
+ const envPath = path.join(__dirname, '.env');
196
+ if (!existsSync(envPath)) {
197
+ // Copy .env.example if it exists
198
+ const examplePath = path.join(__dirname, '.env.example');
199
+ if (existsSync(examplePath)) {
200
+ copyFileSync(examplePath, envPath);
201
+ status.wallet = { ok: false, detail: 'no MNEMONIC in .env (created from .env.example)' };
202
+ } else {
203
+ status.wallet = { ok: false, detail: 'no .env file found' };
204
+ }
205
+ return;
206
+ }
207
+
208
+ try {
209
+ const content = readFileSync(envPath, 'utf-8');
210
+ const match = content.match(/^MNEMONIC\s*=\s*(.+)$/m);
211
+ if (match && match[1].trim().length > 0) {
212
+ const words = match[1].trim().split(/\s+/).length;
213
+ status.wallet = { ok: true, detail: `${words}-word mnemonic configured` };
214
+ } else {
215
+ status.wallet = { ok: false, detail: 'no MNEMONIC in .env' };
216
+ }
217
+ } catch {
218
+ status.wallet = { ok: false, detail: 'could not read .env' };
219
+ }
220
+ }
221
+
222
+ // ─── Status Report ──────────────────────────────────────────────────────────
223
+
224
+ function printReport() {
225
+ const mark = (s) => s.ok ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
226
+ const pad = (s, n) => s.padEnd(n);
227
+
228
+ console.log('');
229
+ console.log('Sentinel AI Connect — Setup');
230
+ console.log('\u2550'.repeat(40));
231
+ console.log(` ${pad('Node.js', 12)} ${mark(status.node)} ${status.node.detail}`);
232
+ console.log(` ${pad('V2Ray', 12)} ${mark(status.v2ray)} ${status.v2ray.detail}`);
233
+ console.log(` ${pad('WireGuard', 12)} ${mark(status.wireguard)} ${status.wireguard.detail}`);
234
+ console.log(` ${pad('Wallet', 12)} ${mark(status.wallet)} ${status.wallet.detail}`);
235
+ console.log('');
236
+
237
+ // Print next steps
238
+ const steps = [];
239
+ if (!status.node.ok) {
240
+ steps.push('Install Node.js >= 20: https://nodejs.org');
241
+ }
242
+ if (!status.v2ray.ok) {
243
+ steps.push('Run: npm run setup (to download V2Ray)');
244
+ }
245
+ if (!status.wallet.ok) {
246
+ steps.push('Set MNEMONIC in .env file');
247
+ steps.push('Or run: npx sentinel-ai wallet create');
248
+ }
249
+
250
+ if (steps.length > 0) {
251
+ console.log(' Next:');
252
+ for (const step of steps) {
253
+ console.log(` ${step}`);
254
+ }
255
+ console.log('');
256
+ } else {
257
+ console.log(' Ready! Run: npx sentinel-ai connect');
258
+ console.log('');
259
+ }
260
+ }
261
+
262
+ // ─── Main ───────────────────────────────────────────────────────────────────
263
+
264
+ async function main() {
265
+ checkNodeVersion();
266
+
267
+ if (!status.node.ok) {
268
+ console.error(`[sentinel-ai] Node.js >= 20 required (found ${process.versions.node})`);
269
+ printReport();
270
+ process.exit(0); // Exit 0 so postinstall doesn't fail npm install
271
+ }
272
+
273
+ const v2rayPath = findV2Ray();
274
+
275
+ // If not found, try parent SDK setup
276
+ if (!v2rayPath) {
277
+ await setupV2Ray();
278
+ }
279
+
280
+ await checkWireGuard();
281
+ checkWallet();
282
+ printReport();
283
+
284
+ // Always exit 0 — missing wallet is expected on first run
285
+ process.exit(0);
286
+ }
287
+
288
+ main().catch((err) => {
289
+ console.error(`[sentinel-ai] Setup error: ${err.message}`);
290
+ process.exit(0); // Don't break npm install
291
+ });
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Sentinel AI Path — Wallet Management
3
+ *
4
+ * Simple wallet operations for AI agents:
5
+ * createWallet() -> { mnemonic, address }
6
+ * importWallet(mnemonic) -> { address }
7
+ * getBalance(mnemonic) -> { address, p2p, udvpn, funded }
8
+ */
9
+
10
+ import {
11
+ createWallet as sdkCreateWallet,
12
+ generateWallet,
13
+ isMnemonicValid,
14
+ getBalance as sdkGetBalance,
15
+ createClient,
16
+ formatP2P,
17
+ LCD_ENDPOINTS,
18
+ DEFAULT_RPC,
19
+ tryWithFallback,
20
+ RPC_ENDPOINTS,
21
+ // v1.5.0: RPC queries (protobuf, ~10x faster than LCD for balance)
22
+ createRpcQueryClientWithFallback,
23
+ rpcQueryBalance,
24
+ } from '../index.js';
25
+
26
+ // ─── Constants ───────────────────────────────────────────────────────────────
27
+
28
+ /** Minimum balance (in udvpn) to consider a wallet "funded" for VPN sessions.
29
+ * Matches connect.js MIN_BALANCE_UDVPN — cheapest node (~4 P2P) + gas. */
30
+ const FUNDED_THRESHOLD = 5_000_000; // 5.0 P2P
31
+
32
+ // ─── createWallet() ──────────────────────────────────────────────────────────
33
+
34
+ /**
35
+ * Generate a brand new Sentinel wallet.
36
+ *
37
+ * @returns {Promise<{mnemonic: string, address: string}>}
38
+ */
39
+ export async function createWallet() {
40
+ try {
41
+ const { mnemonic, account } = await generateWallet();
42
+ return {
43
+ mnemonic,
44
+ address: account.address,
45
+ };
46
+ } catch (err) {
47
+ throw new Error(`Wallet creation failed: ${err.message}`);
48
+ }
49
+ }
50
+
51
+ // ─── importWallet() ──────────────────────────────────────────────────────────
52
+
53
+ /**
54
+ * Import an existing wallet from a BIP39 mnemonic.
55
+ * Validates the mnemonic and derives the sent1... address.
56
+ *
57
+ * @param {string} mnemonic - 12 or 24 word BIP39 phrase
58
+ * @returns {Promise<{address: string}>}
59
+ */
60
+ export async function importWallet(mnemonic) {
61
+ if (!mnemonic || typeof mnemonic !== 'string') {
62
+ throw new Error('importWallet() requires a mnemonic string');
63
+ }
64
+
65
+ if (!isMnemonicValid(mnemonic)) {
66
+ const wordCount = mnemonic.trim().split(/\s+/).length;
67
+ throw new Error(
68
+ `Invalid mnemonic: got ${wordCount} words, need at least 12. ` +
69
+ 'Must be a valid BIP39 phrase.',
70
+ );
71
+ }
72
+
73
+ try {
74
+ const { account } = await sdkCreateWallet(mnemonic);
75
+ return { address: account.address };
76
+ } catch (err) {
77
+ throw new Error(`Wallet import failed: ${err.message}`);
78
+ }
79
+ }
80
+
81
+ // ─── getBalance() ────────────────────────────────────────────────────────────
82
+
83
+ /**
84
+ * Check the P2P token balance of a wallet.
85
+ *
86
+ * @param {string} mnemonic - 12 or 24 word BIP39 phrase
87
+ * @returns {Promise<{address: string, p2p: string, udvpn: number, funded: boolean}>}
88
+ */
89
+ export async function getBalance(mnemonic) {
90
+ if (!mnemonic || typeof mnemonic !== 'string') {
91
+ throw new Error('getBalance() requires a mnemonic string');
92
+ }
93
+
94
+ if (!isMnemonicValid(mnemonic)) {
95
+ throw new Error('Invalid mnemonic. Must be a 12 or 24 word BIP39 phrase.');
96
+ }
97
+
98
+ try {
99
+ // Create wallet to get address
100
+ const { wallet, account } = await sdkCreateWallet(mnemonic);
101
+
102
+ // v1.5.0: Try RPC query first (protobuf, ~10x faster than LCD/signing client)
103
+ // Falls back to signing client + sdkGetBalance if RPC unavailable
104
+ try {
105
+ const rpcClient = await createRpcQueryClientWithFallback();
106
+ const coin = await rpcQueryBalance(rpcClient, account.address, 'udvpn');
107
+ const udvpn = parseInt(coin.amount, 10) || 0;
108
+ return {
109
+ address: account.address,
110
+ p2p: formatP2P(udvpn),
111
+ udvpn,
112
+ funded: udvpn >= FUNDED_THRESHOLD,
113
+ };
114
+ } catch {
115
+ // RPC failed — fall back to signing client (LCD-based)
116
+ }
117
+
118
+ // Fallback: Connect via signing client with RPC endpoints
119
+ const { result: client } = await tryWithFallback(
120
+ RPC_ENDPOINTS,
121
+ async (url) => createClient(url, wallet),
122
+ 'RPC connect (balance check)',
123
+ );
124
+
125
+ // Query balance via signing client
126
+ const bal = await sdkGetBalance(client, account.address);
127
+
128
+ return {
129
+ address: account.address,
130
+ p2p: formatP2P(bal.udvpn),
131
+ udvpn: bal.udvpn,
132
+ funded: bal.udvpn >= FUNDED_THRESHOLD,
133
+ };
134
+ } catch (err) {
135
+ throw new Error(`Balance check failed: ${err.message}`);
136
+ }
137
+ }