@mcpsovereign/sdk 0.1.0 → 0.2.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.
@@ -0,0 +1,498 @@
1
+ /**
2
+ * Wallet Setup Wizard
3
+ *
4
+ * Interactive guide for setting up Lightning wallet
5
+ * MUST be completed before buying/selling (browsing is free)
6
+ */
7
+ import { WALLET_PROVIDERS } from './types.js';
8
+ import { verifyLightningAddress, parseLightningAddress, formatSats } from './lightning.js';
9
+ import { quickSetupLND } from './lnd-setup.js';
10
+ // ============================================================
11
+ // ASCII ART
12
+ // ============================================================
13
+ const WALLET_BANNER = `
14
+ ╔═══════════════════════════════════════════════════════════════════╗
15
+ ║ ║
16
+ ║ ⚡ LIGHTNING WALLET SETUP ⚡ ║
17
+ ║ ║
18
+ ║ mcpSovereign runs on Bitcoin Lightning Network ║
19
+ ║ Fast, cheap, global payments for AI agents ║
20
+ ║ ║
21
+ ╚═══════════════════════════════════════════════════════════════════╝
22
+ `;
23
+ const SELF_HOSTED_BANNER = `
24
+ ╔═══════════════════════════════════════════════════════════════════╗
25
+ ║ ║
26
+ ║ 🖥️ SELF-HOSTED LIGHTNING NODE 🖥️ ║
27
+ ║ ║
28
+ ║ Run your own Lightning node using Neutrino ║
29
+ ║ No Bitcoin Core required - syncs in minutes! ║
30
+ ║ ║
31
+ ╚═══════════════════════════════════════════════════════════════════╝
32
+ `;
33
+ const SUCCESS_BANNER = `
34
+ ╔═══════════════════════════════════════════════════════════════════╗
35
+ ║ ║
36
+ ║ ✅ WALLET CONNECTED! ✅ ║
37
+ ║ ║
38
+ ║ You can now: ║
39
+ ║ 💳 Buy credits with Lightning ║
40
+ ║ 💰 Sell products and earn sats ║
41
+ ║ 🏦 Withdraw earnings anytime ║
42
+ ║ ║
43
+ ╚═══════════════════════════════════════════════════════════════════╝
44
+ `;
45
+ // ============================================================
46
+ // WALLET SETUP WIZARD
47
+ // ============================================================
48
+ export class WalletSetupWizard {
49
+ progress;
50
+ outputHandler;
51
+ inputHandler;
52
+ config = null;
53
+ constructor(outputHandler = console.log, inputHandler) {
54
+ this.outputHandler = outputHandler;
55
+ this.inputHandler = inputHandler;
56
+ this.progress = this.loadProgress();
57
+ }
58
+ // ============================================================
59
+ // OUTPUT HELPERS
60
+ // ============================================================
61
+ print(message) {
62
+ this.outputHandler(message);
63
+ }
64
+ printDivider() {
65
+ this.print('\n' + '─'.repeat(60) + '\n');
66
+ }
67
+ printHeader(emoji, title) {
68
+ this.print(`\n${'═'.repeat(60)}`);
69
+ this.print(` ${emoji} ${title.toUpperCase()}`);
70
+ this.print('═'.repeat(60) + '\n');
71
+ }
72
+ // ============================================================
73
+ // PROGRESS MANAGEMENT
74
+ // ============================================================
75
+ loadProgress() {
76
+ return {
77
+ currentStep: 0,
78
+ completed: false,
79
+ verified: false,
80
+ skipped: false
81
+ };
82
+ }
83
+ saveProgress() {
84
+ // In real implementation, save to ~/.mcpsovereign/wallet-config.json
85
+ }
86
+ // ============================================================
87
+ // STEP: INTRODUCTION
88
+ // ============================================================
89
+ async runIntro() {
90
+ this.print(WALLET_BANNER);
91
+ this.print('Why Lightning? ⚡\n');
92
+ this.print(' • Instant payments (seconds, not days)');
93
+ this.print(' • Near-zero fees (~1 sat for any amount)');
94
+ this.print(' • Global (no banks, no borders)');
95
+ this.print(' • Perfect for AI agents trading value\n');
96
+ this.print('What you need:\n');
97
+ this.print(' 📱 A Lightning wallet with a Lightning Address');
98
+ this.print(' 💳 Some sats to buy credits (or earn by selling)\n');
99
+ this.print('Don\'t have a wallet yet? No problem!');
100
+ this.print('We\'ll help you set one up in about 2 minutes.\n');
101
+ this.print('┌────────────────────────────────────────────────────────┐');
102
+ this.print('│ 🆓 BROWSING THE MARKETPLACE IS ALWAYS FREE │');
103
+ this.print('│ 💳 Wallet only needed to BUY or SELL │');
104
+ this.print('└────────────────────────────────────────────────────────┘\n');
105
+ await this.waitForContinue();
106
+ this.progress.currentStep = 1;
107
+ }
108
+ // ============================================================
109
+ // STEP: CHOOSE PATH
110
+ // ============================================================
111
+ async runChoosePath() {
112
+ this.printHeader('🛤️', 'Choose Your Path');
113
+ this.print('How do you want to connect to Lightning?\n');
114
+ this.print(' 1. 📱 HOSTED WALLET (Recommended for most agents)');
115
+ this.print(' Use a service like Alby or Wallet of Satoshi');
116
+ this.print(' ✓ Ready in 2 minutes');
117
+ this.print(' ✓ No technical setup');
118
+ this.print(' ✓ Works on phone or browser\n');
119
+ this.print(' 2. 🖥️ SELF-HOSTED NODE (For power users)');
120
+ this.print(' Run your own LND node in Docker');
121
+ this.print(' ✓ Full sovereignty');
122
+ this.print(' ✓ No custodial risk');
123
+ this.print(' ✓ Neutrino mode (no full Bitcoin node needed)\n');
124
+ this.print(' 3. ⏭️ SKIP FOR NOW');
125
+ this.print(' Browse the marketplace without a wallet');
126
+ this.print(' You can set up later when ready to buy/sell\n');
127
+ const choice = await this.getChoice('Enter your choice (1-3):', 3);
128
+ switch (choice) {
129
+ case 1: return 'hosted';
130
+ case 2: return 'self-hosted';
131
+ case 3: return 'skip';
132
+ default: return 'hosted';
133
+ }
134
+ }
135
+ // ============================================================
136
+ // STEP: HOSTED WALLET SETUP
137
+ // ============================================================
138
+ async runHostedWalletSetup() {
139
+ this.printHeader('📱', 'Choose a Wallet Provider');
140
+ this.print('Pick a Lightning wallet. All of these support Lightning Addresses:\n');
141
+ const recommended = Object.entries(WALLET_PROVIDERS)
142
+ .filter(([_, p]) => p.recommended && p.id !== 'custom');
143
+ const others = Object.entries(WALLET_PROVIDERS)
144
+ .filter(([_, p]) => !p.recommended && p.id !== 'custom');
145
+ this.print('⭐ RECOMMENDED (easiest to set up):\n');
146
+ recommended.forEach(([key, provider], index) => {
147
+ this.print(` ${index + 1}. ${provider.emoji} ${provider.name}`);
148
+ this.print(` ${provider.description}`);
149
+ this.print(` Type: ${provider.type} | Difficulty: ${provider.difficulty}`);
150
+ this.print(` Platforms: ${provider.platforms.join(', ')}\n`);
151
+ });
152
+ this.print('OTHER OPTIONS:\n');
153
+ others.forEach(([key, provider], index) => {
154
+ this.print(` ${recommended.length + index + 1}. ${provider.emoji} ${provider.name}`);
155
+ this.print(` ${provider.description}`);
156
+ this.print(` Type: ${provider.type} | Difficulty: ${provider.difficulty}\n`);
157
+ });
158
+ this.print(` ${recommended.length + others.length + 1}. 🔧 I already have a Lightning Address\n`);
159
+ const allProviders = [...recommended, ...others];
160
+ const choice = await this.getChoice(`Enter your choice (1-${allProviders.length + 1}):`, allProviders.length + 1);
161
+ if (choice === allProviders.length + 1) {
162
+ // Already has a wallet
163
+ return 'custom';
164
+ }
165
+ const selectedProvider = allProviders[choice - 1][0];
166
+ const providerInfo = WALLET_PROVIDERS[selectedProvider];
167
+ this.progress.provider = selectedProvider;
168
+ // Show setup instructions
169
+ await this.showProviderSetup(providerInfo);
170
+ return selectedProvider;
171
+ }
172
+ /**
173
+ * Show setup instructions for a specific provider
174
+ */
175
+ async showProviderSetup(provider) {
176
+ this.printHeader('🛠️', `Setting Up ${provider.name}`);
177
+ this.print(`Let's set up your ${provider.emoji} ${provider.name} wallet!\n`);
178
+ switch (provider.id) {
179
+ case 'alby':
180
+ this.print('STEP 1: Install Alby Browser Extension');
181
+ this.print(` → Go to: ${provider.setupUrl}`);
182
+ this.print(' → Click "Add to Chrome/Firefox/etc."\n');
183
+ this.print('STEP 2: Create Your Account');
184
+ this.print(' → Click the Alby icon in your browser');
185
+ this.print(' → Sign up with email or Nostr\n');
186
+ this.print('STEP 3: Get Your Lightning Address');
187
+ this.print(' → Your address will be: yourname@getalby.com');
188
+ this.print(' → Find it in Settings → Lightning Address\n');
189
+ break;
190
+ case 'walletofsatoshi':
191
+ this.print('STEP 1: Download the App');
192
+ this.print(` → Go to: ${provider.setupUrl}`);
193
+ this.print(' → Available on iOS and Android\n');
194
+ this.print('STEP 2: Open the App');
195
+ this.print(' → No account needed! Just open and you\'re ready\n');
196
+ this.print('STEP 3: Get Your Lightning Address');
197
+ this.print(' → Tap "Receive"');
198
+ this.print(' → Your address: yourname@walletofsatoshi.com\n');
199
+ break;
200
+ case 'phoenix':
201
+ this.print('STEP 1: Download Phoenix');
202
+ this.print(` → Go to: ${provider.setupUrl}`);
203
+ this.print(' → Available on iOS and Android\n');
204
+ this.print('STEP 2: Create Your Wallet');
205
+ this.print(' → Write down your 12-word seed phrase!');
206
+ this.print(' → This is your backup - keep it safe!\n');
207
+ this.print('STEP 3: Get Your Lightning Address');
208
+ this.print(' → Go to Settings → Lightning Address');
209
+ this.print(' → Format: yourname@phoenix.acinq.co\n');
210
+ break;
211
+ default:
212
+ this.print(`STEP 1: Go to ${provider.setupUrl}`);
213
+ this.print('STEP 2: Follow their setup instructions');
214
+ this.print('STEP 3: Get your Lightning Address\n');
215
+ }
216
+ this.print('┌────────────────────────────────────────────────────────┐');
217
+ this.print('│ 💡 TIP: Your Lightning Address looks like an email: │');
218
+ this.print('│ yourname@getalby.com │');
219
+ this.print('│ yourname@walletofsatoshi.com │');
220
+ this.print('└────────────────────────────────────────────────────────┘\n');
221
+ await this.waitForContinue('Press Enter when you have your Lightning Address...');
222
+ }
223
+ // ============================================================
224
+ // STEP: SELF-HOSTED NODE SETUP
225
+ // ============================================================
226
+ async runSelfHostedSetup() {
227
+ this.print(SELF_HOSTED_BANNER);
228
+ this.print('Self-hosting gives you full control over your Bitcoin.\n');
229
+ this.print('What you\'ll get:');
230
+ this.print(' 🖥️ Your own LND Lightning node');
231
+ this.print(' ⚡ Neutrino mode (syncs in minutes, not days)');
232
+ this.print(' 🐳 Runs in Docker (easy management)');
233
+ this.print(' 🔐 Your keys, your Bitcoin\n');
234
+ this.print('Requirements:');
235
+ this.print(' • Docker installed and running');
236
+ this.print(' • ~5GB disk space');
237
+ this.print(' • Internet connection\n');
238
+ const proceed = await this.getInput('Run automated setup? (yes/no): ');
239
+ if (proceed.toLowerCase() !== 'yes' && proceed.toLowerCase() !== 'y') {
240
+ this.print('\nSetup cancelled. You can run it later with:');
241
+ this.print(' npx @mcpsovereign/sdk setup-lnd\n');
242
+ return false;
243
+ }
244
+ this.print('\n🚀 Starting automated LND setup...\n');
245
+ // Run the setup
246
+ const result = await quickSetupLND();
247
+ if (!result.success) {
248
+ this.print(`\n❌ Setup failed: ${result.error}`);
249
+ this.print('\nLogs:');
250
+ result.logs.slice(-10).forEach(log => this.print(` ${log}`));
251
+ return false;
252
+ }
253
+ // Show success and seed
254
+ this.print('\n✅ LND node is running!\n');
255
+ if (result.walletSeed) {
256
+ this.print('┌────────────────────────────────────────────────────────┐');
257
+ this.print('│ 🔐 IMPORTANT: BACKUP YOUR SEED PHRASE! │');
258
+ this.print('├────────────────────────────────────────────────────────┤');
259
+ this.print('│ Write these 24 words down and store them safely: │');
260
+ this.print('│ │');
261
+ for (let i = 0; i < 24; i += 4) {
262
+ const words = result.walletSeed.slice(i, i + 4);
263
+ const line = words.map((w, j) => `${i + j + 1}. ${w}`).join(' ');
264
+ this.print(`│ ${line.padEnd(54)}│`);
265
+ }
266
+ this.print('│ │');
267
+ this.print('│ ⚠️ If you lose these words, you lose your Bitcoin! │');
268
+ this.print('└────────────────────────────────────────────────────────┘\n');
269
+ }
270
+ if (result.credentials) {
271
+ this.config = {
272
+ provider: 'zeus', // Self-hosted
273
+ nodeUri: `${result.credentials.restHost}`,
274
+ setupComplete: true,
275
+ verified: true,
276
+ verifiedAt: new Date().toISOString(),
277
+ createdAt: new Date().toISOString()
278
+ };
279
+ this.print('Node connection info:');
280
+ this.print(` REST: ${result.credentials.restHost}`);
281
+ this.print(` gRPC: ${result.credentials.grpcHost}\n`);
282
+ }
283
+ this.progress.verified = true;
284
+ this.progress.provider = 'zeus';
285
+ return true;
286
+ }
287
+ // ============================================================
288
+ // STEP: ENTER LIGHTNING ADDRESS
289
+ // ============================================================
290
+ async runEnterAddress() {
291
+ this.printHeader('📧', 'Enter Your Lightning Address');
292
+ this.print('Your Lightning Address is like an email for Bitcoin.\n');
293
+ this.print('Examples:');
294
+ this.print(' • myagent@getalby.com');
295
+ this.print(' • satoshi@walletofsatoshi.com');
296
+ this.print(' • agent007@phoenix.acinq.co\n');
297
+ const address = await this.getInput('Your Lightning Address: ');
298
+ if (!address) {
299
+ this.print('\n⚠️ No address entered.');
300
+ return null;
301
+ }
302
+ // Validate format
303
+ const parsed = parseLightningAddress(address);
304
+ if (!parsed || !parsed.valid) {
305
+ this.print('\n❌ Invalid format. Lightning addresses look like: username@domain.com');
306
+ return null;
307
+ }
308
+ this.progress.lightningAddress = parsed.address;
309
+ return parsed.address;
310
+ }
311
+ // ============================================================
312
+ // STEP: VERIFY ADDRESS
313
+ // ============================================================
314
+ async runVerifyAddress(address) {
315
+ this.printHeader('✅', 'Verifying Your Wallet');
316
+ this.print(`Verifying: ${address}\n`);
317
+ this.print('Checking if your wallet can receive payments...\n');
318
+ const result = await verifyLightningAddress(address);
319
+ if (!result.valid) {
320
+ this.print(`❌ Verification failed: ${result.error}`);
321
+ this.print('\nPossible issues:');
322
+ this.print(' • The address might be typed incorrectly');
323
+ this.print(' • The wallet service might be down');
324
+ this.print(' • The account might not be fully set up yet\n');
325
+ return false;
326
+ }
327
+ this.print('✅ Wallet verified successfully!\n');
328
+ if (result.info?.metadata) {
329
+ this.print('Wallet details:');
330
+ if (result.info.metadata.description) {
331
+ this.print(` 📝 ${result.info.metadata.description}`);
332
+ }
333
+ if (result.info.metadata.minSendable) {
334
+ this.print(` 📉 Min receive: ${formatSats(result.info.metadata.minSendable / 1000)}`);
335
+ }
336
+ if (result.info.metadata.maxSendable) {
337
+ this.print(` 📈 Max receive: ${formatSats(result.info.metadata.maxSendable / 1000)}`);
338
+ }
339
+ this.print('');
340
+ }
341
+ // Save config
342
+ this.config = {
343
+ provider: this.progress.provider || 'custom',
344
+ lightningAddress: address,
345
+ setupComplete: true,
346
+ verified: true,
347
+ verifiedAt: new Date().toISOString(),
348
+ createdAt: new Date().toISOString()
349
+ };
350
+ this.progress.verified = true;
351
+ return true;
352
+ }
353
+ // ============================================================
354
+ // STEP: COMPLETE
355
+ // ============================================================
356
+ async runComplete() {
357
+ this.print(SUCCESS_BANNER);
358
+ this.print('Your wallet setup:\n');
359
+ this.print('┌────────────────────────────────────────────────────────┐');
360
+ if (this.config?.lightningAddress) {
361
+ this.print(`│ 📧 Address: ${this.config.lightningAddress.padEnd(40)}│`);
362
+ }
363
+ if (this.config?.provider) {
364
+ const provider = WALLET_PROVIDERS[this.config.provider];
365
+ this.print(`│ ${provider.emoji} Provider: ${provider.name.padEnd(39)}│`);
366
+ }
367
+ this.print(`│ ✅ Verified: ${this.config?.verified ? 'Yes' : 'No'} │`);
368
+ this.print('└────────────────────────────────────────────────────────┘\n');
369
+ this.print('What happens next:\n');
370
+ this.print(' 1. Complete onboarding to set up your store');
371
+ this.print(' 2. Buy credits with Lightning to start trading');
372
+ this.print(' 3. Create products and earn sats!\n');
373
+ this.print('Credit packages:\n');
374
+ this.print(' 💰 1,000 credits = 10,000 sats (~$5)');
375
+ this.print(' 💰 5,000 credits = 50,000 sats (~$25)');
376
+ this.print(' 💰 10,000 credits = 100,000 sats (~$50)\n');
377
+ this.progress.completed = true;
378
+ this.saveProgress();
379
+ }
380
+ // ============================================================
381
+ // STEP: SKIP
382
+ // ============================================================
383
+ async runSkip() {
384
+ this.printHeader('⏭️', 'Skipping Wallet Setup');
385
+ this.print('No problem! You can browse the marketplace without a wallet.\n');
386
+ this.print('What you CAN do without a wallet:');
387
+ this.print(' 🔍 Browse products');
388
+ this.print(' 👀 View prices and reviews');
389
+ this.print(' 📖 Read documentation');
390
+ this.print(' 🏪 Set up your store locally (FREE)\n');
391
+ this.print('What you\'ll need a wallet for:');
392
+ this.print(' 💳 Buying credits');
393
+ this.print(' 💰 Receiving payments from sales');
394
+ this.print(' 📤 Publishing to marketplace\n');
395
+ this.print('You can set up your wallet anytime with:');
396
+ this.print(' npx @mcpsovereign/sdk setup-wallet\n');
397
+ this.progress.skipped = true;
398
+ this.progress.completed = true;
399
+ this.saveProgress();
400
+ }
401
+ // ============================================================
402
+ // MAIN RUN METHOD
403
+ // ============================================================
404
+ async run() {
405
+ // Step 1: Introduction
406
+ await this.runIntro();
407
+ // Step 2: Choose path
408
+ const path = await this.runChoosePath();
409
+ if (path === 'skip') {
410
+ await this.runSkip();
411
+ return { config: null, skipped: true };
412
+ }
413
+ if (path === 'self-hosted') {
414
+ // Self-hosted LND setup
415
+ const success = await this.runSelfHostedSetup();
416
+ if (success) {
417
+ await this.runComplete();
418
+ return { config: this.config, skipped: false };
419
+ }
420
+ // Fall back to hosted option
421
+ this.print('\nFalling back to hosted wallet option...\n');
422
+ }
423
+ // Hosted wallet setup
424
+ const provider = await this.runHostedWalletSetup();
425
+ if (!provider) {
426
+ await this.runSkip();
427
+ return { config: null, skipped: true };
428
+ }
429
+ // Get Lightning Address
430
+ let address = null;
431
+ let verified = false;
432
+ while (!verified) {
433
+ address = await this.runEnterAddress();
434
+ if (!address) {
435
+ const retry = await this.getInput('Try again? (yes/no): ');
436
+ if (retry.toLowerCase() !== 'yes' && retry.toLowerCase() !== 'y') {
437
+ await this.runSkip();
438
+ return { config: null, skipped: true };
439
+ }
440
+ continue;
441
+ }
442
+ verified = await this.runVerifyAddress(address);
443
+ if (!verified) {
444
+ const retry = await this.getInput('Try a different address? (yes/no): ');
445
+ if (retry.toLowerCase() !== 'yes' && retry.toLowerCase() !== 'y') {
446
+ // Allow proceeding with unverified (user's choice)
447
+ const proceed = await this.getInput('Proceed with unverified address? (yes/no): ');
448
+ if (proceed.toLowerCase() === 'yes' || proceed.toLowerCase() === 'y') {
449
+ this.config = {
450
+ provider: provider,
451
+ lightningAddress: address,
452
+ setupComplete: true,
453
+ verified: false,
454
+ createdAt: new Date().toISOString()
455
+ };
456
+ break;
457
+ }
458
+ }
459
+ }
460
+ }
461
+ await this.runComplete();
462
+ return { config: this.config, skipped: false };
463
+ }
464
+ // ============================================================
465
+ // INPUT HELPERS
466
+ // ============================================================
467
+ async waitForContinue(prompt = 'Press Enter to continue...') {
468
+ await this.getInput(prompt);
469
+ }
470
+ async getInput(prompt) {
471
+ if (this.inputHandler) {
472
+ return await this.inputHandler(prompt);
473
+ }
474
+ this.print(prompt);
475
+ return '';
476
+ }
477
+ async getChoice(prompt, max) {
478
+ if (this.inputHandler) {
479
+ const options = Array.from({ length: max }, (_, i) => (i + 1).toString());
480
+ const response = await this.inputHandler(prompt, options);
481
+ const num = parseInt(response);
482
+ if (num >= 1 && num <= max) {
483
+ return num;
484
+ }
485
+ }
486
+ return 1;
487
+ }
488
+ // ============================================================
489
+ // GETTERS
490
+ // ============================================================
491
+ getConfig() {
492
+ return this.config;
493
+ }
494
+ getProgress() {
495
+ return { ...this.progress };
496
+ }
497
+ }
498
+ export default WalletSetupWizard;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcpsovereign/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "TypeScript SDK for mcpSovereign - The AI Agent Marketplace",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -28,7 +28,9 @@
28
28
  "dev": "tsc --watch",
29
29
  "postinstall": "node dist/setup.js setup 2>/dev/null || echo 'Run: npx mcpsovereign setup'"
30
30
  },
31
- "dependencies": {},
31
+ "dependencies": {
32
+ "@mcpsovereign/types": "workspace:*"
33
+ },
32
34
  "devDependencies": {
33
35
  "@types/node": "^22.10.7",
34
36
  "typescript": "^5.7.3"
@@ -49,7 +51,7 @@
49
51
  ],
50
52
  "repository": {
51
53
  "type": "git",
52
- "url": "https://github.com/mcpsovereign/mcpsovereign-sdk"
54
+ "url": "https://github.com/mcpsovereign/sdk"
53
55
  },
54
56
  "homepage": "https://mcpsovereign.com",
55
57
  "license": "MIT"