nervepay 1.2.1 → 1.2.8

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.
@@ -288,190 +288,452 @@ program
288
288
 
289
289
  program
290
290
  .command('pair')
291
- .description('Quick pair gateway using a dashboard pairing code')
292
- .requiredOption('--code <code>', '6-character pairing code from NervePay dashboard')
291
+ .description('Pair gateway via device node protocol (default) or pairing code (--code)')
292
+ .option('--code <code>', '6-character pairing code (legacy flow)')
293
293
  .option('--api-url <url>', 'NervePay API URL', 'https://api.nervepay.xyz')
294
294
  .option('--gateway-url <url>', 'Gateway URL (e.g. ws://127.0.0.1:18789)')
295
- .option('--gateway-token <token>', 'Gateway authentication token')
296
- .option('--name <name>', 'Agent name', 'OpenClaw Gateway')
295
+ .option('--gateway-token <token>', 'Gateway authentication token (only for --code flow)')
296
+ .option('--name <name>', 'Gateway display name', 'OpenClaw Gateway')
297
+ .option('--timeout <seconds>', 'Approval wait timeout in seconds', '300')
297
298
  .action(async (options) => {
298
- console.log(chalk.cyan('\nšŸ”— NervePay Quick Pair\n'));
299
- console.log(chalk.gray(' Code:'), chalk.white(options.code));
299
+ if (options.code) {
300
+ await legacyCodePairing(options);
301
+ } else {
302
+ await deviceNodePairing(options);
303
+ }
304
+ });
305
+
306
+ /**
307
+ * Device node pairing — connects to gateway via WebSocket, signs challenge
308
+ * with the agent's DID Ed25519 key, and receives a scoped device token.
309
+ */
310
+ async function deviceNodePairing(options) {
311
+ const { signRawBytes, deriveDeviceId, getPublicKeyFromPrivate } = await import('../dist/utils/crypto.js');
300
312
 
313
+ console.log(chalk.cyan('\nšŸ”— NervePay Device Node Pairing\n'));
314
+
315
+ try {
316
+ // 1. Load agent credentials (must exist — run setup first)
317
+ let config;
301
318
  try {
302
- // Step 1: Load existing credentials or create new identity
303
- let agentDid, privateKey, mnemonic, claimUrl, sessionId, isNew = false;
319
+ config = await loadConfig();
320
+ } catch {
321
+ console.error(chalk.red('āŒ No agent credentials found.'));
322
+ console.error(chalk.yellow(' Run:'), chalk.cyan('nervepay setup'), chalk.yellow('first'));
323
+ process.exit(1);
324
+ }
304
325
 
305
- try {
306
- const config = await loadConfig();
307
- agentDid = config.agentDid;
308
- privateKey = config.privateKey;
309
- console.log(chalk.green('āœ“ Using existing agent identity'));
310
- console.log(chalk.gray(' DID:'), agentDid);
311
- } catch {
312
- // No existing config — create a new pending identity
313
- console.log(chalk.cyan(' No existing identity found, creating one...\n'));
314
- const tempClient = new NervePayClient({ apiUrl: options.apiUrl });
315
- const reg = await identity.registerPendingIdentity(tempClient, {
316
- name: options.name,
317
- description: 'Gateway operator',
318
- });
319
- agentDid = reg.did;
320
- privateKey = reg.private_key;
321
- mnemonic = reg.mnemonic;
322
- claimUrl = reg.claim_url;
323
- sessionId = reg.session_id;
324
- isNew = true;
325
- console.log(chalk.green(' āœ“ Agent identity created'));
326
- console.log(chalk.gray(' DID:'), agentDid);
327
-
328
- // Show claim URL and offer to open browser
329
- if (claimUrl) {
330
- console.log(chalk.cyan('\n šŸ‘¤ Claim this agent to link it to your NervePay account:'));
331
- console.log(chalk.yellow(` ${claimUrl}`));
332
- console.log(chalk.gray(' (This links the agent to your dashboard for management)\n'));
326
+ const { agentDid, privateKey, apiUrl } = config;
327
+ console.log(chalk.green('āœ“ Agent identity loaded'));
328
+ console.log(chalk.gray(' DID:'), agentDid);
333
329
 
334
- try {
335
- const open = await import('open');
336
- await open.default(claimUrl);
337
- console.log(chalk.gray(' Opened in browser.'));
338
- } catch {
339
- console.log(chalk.gray(' Open the URL above in your browser.'));
330
+ // 2. Find gateway URL from config or --gateway-url flag
331
+ let gatewayUrl = options.gatewayUrl;
332
+ if (!gatewayUrl) {
333
+ const openclawConfig = await readOpenClawConfig();
334
+ const gw = extractGatewayConfig(openclawConfig);
335
+ gatewayUrl = gw.url;
336
+ }
337
+
338
+ if (!gatewayUrl) {
339
+ console.error(chalk.red('\nāŒ Could not find gateway URL'));
340
+ console.error(chalk.yellow(' Provide it via one of:'));
341
+ console.error(chalk.gray(' --gateway-url <url> (e.g. ws://127.0.0.1:18789)'));
342
+ console.error(chalk.gray(' ~/.openclaw/openclaw.json'));
343
+ process.exit(1);
344
+ }
345
+
346
+ // Normalize to ws:// URL
347
+ let wsUrl = gatewayUrl.replace(/\/$/, '');
348
+ if (wsUrl.startsWith('https://')) wsUrl = 'wss://' + wsUrl.slice('https://'.length);
349
+ else if (wsUrl.startsWith('http://')) wsUrl = 'ws://' + wsUrl.slice('http://'.length);
350
+ else if (!wsUrl.startsWith('ws://') && !wsUrl.startsWith('wss://')) wsUrl = 'ws://' + wsUrl;
351
+
352
+ console.log(chalk.gray(' Gateway:'), wsUrl);
353
+
354
+ // 3. Derive device ID from agent's public key
355
+ const publicKeyBase58 = await getPublicKeyFromPrivate(privateKey);
356
+ const deviceId = deriveDeviceId(publicKeyBase58);
357
+ console.log(chalk.gray(' Device ID:'), deviceId.slice(0, 16) + '...');
358
+
359
+ // 4. Connect to gateway via WebSocket
360
+ console.log(chalk.cyan('\nšŸ“” Connecting to gateway...'));
361
+ const WebSocket = (await import('ws')).default;
362
+
363
+ const ws = new WebSocket(wsUrl, { rejectUnauthorized: false });
364
+ const timeoutMs = parseInt(options.timeout, 10) * 1000;
365
+
366
+ // Pre-compute crypto values before entering the WebSocket flow
367
+ // (avoids async gaps in the message handler that cause race conditions)
368
+ const { decodeBase58 } = await import('../dist/utils/crypto.js');
369
+ const pubKeyBytes = decodeBase58(publicKeyBase58);
370
+ const pubKeyB64 = Buffer.from(pubKeyBytes).toString('base64');
371
+
372
+ const result = await new Promise((resolve, reject) => {
373
+ let settled = false;
374
+ let connectId = null;
375
+ let pairId = null;
376
+ let requestId = null;
377
+ let lastError = null;
378
+
379
+ function settle(fn, value) {
380
+ if (settled) return;
381
+ settled = true;
382
+ clearTimeout(timer);
383
+ fn(value);
384
+ }
385
+
386
+ const timer = setTimeout(() => {
387
+ ws.close();
388
+ settle(reject, new Error(`Pairing approval timed out (waited ${options.timeout}s)`));
389
+ }, timeoutMs + 15000);
390
+
391
+ ws.on('error', (err) => {
392
+ settle(reject, new Error(`WebSocket error: ${err.message}`));
393
+ });
394
+
395
+ ws.on('close', (code, reason) => {
396
+ // Delay slightly to let any pending message handler finish
397
+ setTimeout(() => {
398
+ const reasonStr = reason?.toString() || '';
399
+ const detail = lastError
400
+ ? lastError
401
+ : reasonStr
402
+ ? `code=${code} reason=${reasonStr}`
403
+ : `code=${code}`;
404
+ settle(reject, new Error(`Gateway closed connection (${detail})`));
405
+ }, 100);
406
+ });
407
+
408
+ ws.on('message', async (data) => {
409
+ try {
410
+ const raw = data.toString();
411
+ const frame = JSON.parse(raw);
412
+
413
+ // Step 5: Receive connect.challenge → sign nonce
414
+ if (frame.event === 'connect.challenge') {
415
+ const nonce = frame.payload?.nonce || '';
416
+ console.log(chalk.green('āœ“ Challenge received'));
417
+
418
+ const nonceBytes = new TextEncoder().encode(nonce);
419
+ const signatureB64 = await signRawBytes(privateKey, nonceBytes);
420
+ const signedAt = Date.now();
421
+
422
+ // Step 6: Send connect request as operator with device identity
423
+ connectId = crypto.randomUUID();
424
+ const connectReq = {
425
+ type: 'request',
426
+ id: connectId,
427
+ method: 'connect',
428
+ params: {
429
+ role: 'operator',
430
+ scopes: ['operator.read', 'operator.write'],
431
+ client: {
432
+ id: `nervepay-cli-${crypto.randomUUID().slice(0, 8)}`,
433
+ version: '1.2.6',
434
+ platform: 'cli',
435
+ mode: 'pairing',
436
+ },
437
+ device: {
438
+ id: deviceId,
439
+ publicKey: pubKeyB64,
440
+ signature: signatureB64,
441
+ signedAt,
442
+ nonce,
443
+ },
444
+ },
445
+ };
446
+ ws.send(JSON.stringify(connectReq));
447
+ return;
448
+ }
449
+
450
+ // Connect response
451
+ if (frame.type === 'response' && frame.id === connectId) {
452
+ if (frame.ok) {
453
+ console.log(chalk.green('āœ“ Connected to gateway'));
454
+
455
+ // Step 7: Send node.pair.request
456
+ pairId = crypto.randomUUID();
457
+ const pairReq = {
458
+ type: 'request',
459
+ id: pairId,
460
+ method: 'node.pair.request',
461
+ params: {
462
+ displayName: `NervePay (${agentDid.split(':').pop().slice(0, 8)})`,
463
+ platform: 'cli',
464
+ },
465
+ };
466
+ ws.send(JSON.stringify(pairReq));
467
+ } else {
468
+ lastError = `Connect rejected: ${frame.error || 'Unknown error'}`;
469
+ console.error(chalk.red(` ${lastError}`));
470
+ ws.close();
471
+ settle(reject, new Error(lastError));
472
+ }
473
+ return;
340
474
  }
341
475
 
342
- // Poll for claim (30 seconds — quick pair shouldn't block too long)
343
- console.log(chalk.cyan(' ā³ Waiting for claim (30s timeout)...\n'));
344
- let claimed = false;
345
- for (let i = 0; i < 6; i++) {
346
- await new Promise((r) => setTimeout(r, 5000));
347
- try {
348
- const status = await fetch(`${options.apiUrl}/v1/agent-identity/register-pending/${sessionId}/status`);
349
- const data = await status.json();
350
- if (data.status === 'claimed') {
351
- claimed = true;
352
- console.log(chalk.green(' āœ“ Agent claimed successfully!\n'));
353
- break;
354
- } else if (data.status === 'expired') {
355
- break;
356
- }
357
- process.stdout.write(chalk.gray('.'));
358
- } catch {
359
- process.stdout.write(chalk.gray('.'));
476
+ // Pair request response → extract requestId
477
+ if (frame.type === 'response' && frame.id === pairId) {
478
+ if (frame.ok) {
479
+ requestId = frame.payload?.requestId || '';
480
+ console.log(chalk.green('āœ“ Pairing request submitted'));
481
+ console.log(chalk.cyan('\nā³ Waiting for gateway owner approval...'));
482
+ console.log(chalk.gray(` Approve with: openclaw devices approve ${requestId}`));
483
+ console.log(chalk.gray(` Timeout: ${options.timeout}s\n`));
484
+ } else {
485
+ lastError = `Pair request rejected: ${frame.error || 'Unknown error'}`;
486
+ console.error(chalk.red(` ${lastError}`));
487
+ ws.close();
488
+ settle(reject, new Error(lastError));
360
489
  }
490
+ return;
361
491
  }
362
492
 
363
- if (!claimed) {
364
- console.log(chalk.yellow('\n āš ļø Not claimed yet — continuing with pairing.'));
365
- console.log(chalk.gray(' You can claim later at:'), chalk.yellow(claimUrl));
493
+ // Step 8: node.pair.resolved event
494
+ if (frame.event === 'node.pair.resolved') {
495
+ const rid = frame.payload?.requestId;
496
+ if (rid && rid !== requestId) return;
497
+
498
+ const decision = frame.payload?.decision;
499
+ if (decision === 'approved') {
500
+ const token = frame.payload?.token || '';
501
+ const nodeId = frame.payload?.nodeId || '';
502
+ ws.close();
503
+ settle(resolve, { token, nodeId, requestId });
504
+ } else if (decision === 'rejected') {
505
+ ws.close();
506
+ settle(reject, new Error('Pairing request was rejected by the gateway owner'));
507
+ } else {
508
+ ws.close();
509
+ settle(reject, new Error(`Unexpected pairing decision: ${decision}`));
510
+ }
511
+ return;
366
512
  }
367
- }
368
513
 
369
- // Show mnemonic
370
- if (mnemonic) {
371
- console.log(chalk.cyan('\n šŸ” Recovery mnemonic:'));
372
- console.log(chalk.yellow(` ${mnemonic}`));
373
- console.log(chalk.red(' āš ļø Save this — you can recover your keys with it!\n'));
514
+ // Log unhandled frames for debugging
515
+ if (frame.type === 'response' || frame.error) {
516
+ console.log(chalk.gray(' [debug] Unhandled frame:'), JSON.stringify(frame).slice(0, 200));
517
+ }
518
+ } catch (err) {
519
+ // Ignore parse errors for non-JSON messages (ping, etc)
374
520
  }
521
+ });
522
+ });
523
+
524
+ // 9. Send device token to NervePay API
525
+ console.log(chalk.green('\nāœ“ Pairing approved! Saving to NervePay...'));
526
+
527
+ const client = new NervePayClient({
528
+ apiUrl: options.apiUrl || apiUrl,
529
+ agentDid,
530
+ privateKey,
531
+ });
532
+
533
+ const apiResult = await gateway.completeDevicePairing(client, {
534
+ device_token: result.token,
535
+ device_id: deviceId,
536
+ gateway_url: gatewayUrl,
537
+ gateway_name: options.name,
538
+ });
539
+
540
+ console.log(chalk.green('\nāœ… Device pairing complete!'));
541
+ console.log(chalk.gray(' Gateway ID:'), apiResult.gateway_id || 'created');
542
+ console.log(chalk.gray(' Device ID: '), deviceId.slice(0, 16) + '...');
543
+ console.log(chalk.gray(' Agent DID: '), agentDid);
544
+ console.log(chalk.gray('\n Your gateway is now live in the NervePay dashboard.'));
545
+ console.log(chalk.gray(' Go to Mission Control to spawn agents and manage tasks.\n'));
546
+ } catch (error) {
547
+ console.error(chalk.red('\nāŒ Device pairing failed:'), error.message);
548
+ process.exit(1);
549
+ }
550
+ }
551
+
552
+ /**
553
+ * Legacy code-based pairing flow (--code flag provided).
554
+ */
555
+ async function legacyCodePairing(options) {
556
+ console.log(chalk.cyan('\nšŸ”— NervePay Code Pairing\n'));
557
+ console.log(chalk.gray(' Code:'), chalk.white(options.code));
558
+
559
+ try {
560
+ // Step 1: Load existing credentials or create new identity
561
+ let agentDid, privateKey, mnemonic, claimUrl, sessionId, isNew = false;
562
+
563
+ try {
564
+ const config = await loadConfig();
565
+ agentDid = config.agentDid;
566
+ privateKey = config.privateKey;
567
+ console.log(chalk.green('āœ“ Using existing agent identity'));
568
+ console.log(chalk.gray(' DID:'), agentDid);
569
+ } catch {
570
+ // No existing config — create a new pending identity
571
+ console.log(chalk.cyan(' No existing identity found, creating one...\n'));
572
+ const tempClient = new NervePayClient({ apiUrl: options.apiUrl });
573
+ const reg = await identity.registerPendingIdentity(tempClient, {
574
+ name: options.name,
575
+ description: 'Gateway operator',
576
+ });
577
+ agentDid = reg.did;
578
+ privateKey = reg.private_key;
579
+ mnemonic = reg.mnemonic;
580
+ claimUrl = reg.claim_url;
581
+ sessionId = reg.session_id;
582
+ isNew = true;
583
+ console.log(chalk.green(' āœ“ Agent identity created'));
584
+ console.log(chalk.gray(' DID:'), agentDid);
585
+
586
+ // Show claim URL and offer to open browser
587
+ if (claimUrl) {
588
+ console.log(chalk.cyan('\n šŸ‘¤ Claim this agent to link it to your NervePay account:'));
589
+ console.log(chalk.yellow(` ${claimUrl}`));
590
+ console.log(chalk.gray(' (This links the agent to your dashboard for management)\n'));
375
591
 
376
- // Save credentials immediately so they persist even if pairing fails
377
592
  try {
378
- const { mkdir } = await import('fs/promises');
379
- await mkdir(join(homedir(), '.nervepay'), { recursive: true });
380
- await writeFile(
381
- NERVEPAY_CREDS_PATH,
382
- JSON.stringify({
383
- agent_did: agentDid,
384
- private_key: privateKey,
385
- mnemonic: mnemonic || undefined,
386
- api_url: options.apiUrl,
387
- created_at: new Date().toISOString(),
388
- }, null, 2)
389
- );
390
- console.log(chalk.green(' āœ“ Credentials saved to ~/.nervepay/credentials.json'));
391
-
392
- // Update OpenClaw config if it exists
593
+ const open = await import('open');
594
+ await open.default(claimUrl);
595
+ console.log(chalk.gray(' Opened in browser.'));
596
+ } catch {
597
+ console.log(chalk.gray(' Open the URL above in your browser.'));
598
+ }
599
+
600
+ // Poll for claim (30 seconds — quick pair shouldn't block too long)
601
+ console.log(chalk.cyan(' ā³ Waiting for claim (30s timeout)...\n'));
602
+ let claimed = false;
603
+ for (let i = 0; i < 6; i++) {
604
+ await new Promise((r) => setTimeout(r, 5000));
393
605
  try {
394
- const ocConfigPath = await findOpenClawConfigPath();
395
- if (ocConfigPath) {
396
- const existingConfig = JSON.parse(await readFile(ocConfigPath, 'utf-8'));
397
- if (!existingConfig.plugins) existingConfig.plugins = {};
398
- if (!existingConfig.plugins.entries) existingConfig.plugins.entries = {};
399
- if (!existingConfig.plugins.entries.nervepay) {
400
- existingConfig.plugins.entries.nervepay = { enabled: true, config: {} };
401
- }
402
- existingConfig.plugins.entries.nervepay.config = {
403
- ...existingConfig.plugins.entries.nervepay.config,
404
- apiUrl: options.apiUrl,
405
- agentDid,
406
- privateKey,
407
- };
408
- await writeFile(ocConfigPath, JSON.stringify(existingConfig, null, 2));
409
- console.log(chalk.green(' āœ“ OpenClaw config updated'));
606
+ const status = await fetch(`${options.apiUrl}/v1/agent-identity/register-pending/${sessionId}/status`);
607
+ const data = await status.json();
608
+ if (data.status === 'claimed') {
609
+ claimed = true;
610
+ console.log(chalk.green(' āœ“ Agent claimed successfully!\n'));
611
+ break;
612
+ } else if (data.status === 'expired') {
613
+ break;
410
614
  }
615
+ process.stdout.write(chalk.gray('.'));
411
616
  } catch {
412
- // Non-fatal
617
+ process.stdout.write(chalk.gray('.'));
413
618
  }
414
- } catch (e) {
415
- console.log(chalk.yellow(' āš ļø Could not save credentials:'), e.message);
416
619
  }
417
- }
418
620
 
419
- // Step 2: Read gateway config (from flags, env, or config files)
420
- console.log(chalk.cyan('šŸ“” Reading gateway config...'));
421
-
422
- let gatewayUrl = options.gatewayUrl;
423
- let gatewayToken = options.gatewayToken;
424
-
425
- // Try OpenClaw config if flags not provided
426
- if (!gatewayUrl || !gatewayToken) {
427
- const openclawConfig = await readOpenClawConfig();
428
- const gw = extractGatewayConfig(openclawConfig);
429
- gatewayUrl = gatewayUrl || gw.url;
430
- gatewayToken = gatewayToken || gw.token;
621
+ if (!claimed) {
622
+ console.log(chalk.yellow('\n āš ļø Not claimed yet — continuing with pairing.'));
623
+ console.log(chalk.gray(' You can claim later at:'), chalk.yellow(claimUrl));
624
+ }
431
625
  }
432
626
 
433
- // Default URL if we have a token but no URL
434
- if (gatewayToken && !gatewayUrl) {
435
- gatewayUrl = 'http://127.0.0.1:18789';
627
+ // Show mnemonic
628
+ if (mnemonic) {
629
+ console.log(chalk.cyan('\n šŸ” Recovery mnemonic:'));
630
+ console.log(chalk.yellow(` ${mnemonic}`));
631
+ console.log(chalk.red(' āš ļø Save this — you can recover your keys with it!\n'));
436
632
  }
437
633
 
438
- if (!gatewayToken) {
439
- console.error(chalk.red('\nāŒ Could not find gateway token'));
440
- console.error(chalk.yellow(' Provide it via one of:'));
441
- console.error(chalk.gray(' --gateway-token <token>'));
442
- console.error(chalk.gray(' ~/.openclaw/openclaw.json (gateway.auth.token)'));
443
- console.error(chalk.gray(' OPENCLAW_GATEWAY_TOKEN env var'));
444
- process.exit(1);
634
+ // Save credentials immediately so they persist even if pairing fails
635
+ try {
636
+ const { mkdir } = await import('fs/promises');
637
+ await mkdir(join(homedir(), '.nervepay'), { recursive: true });
638
+ await writeFile(
639
+ NERVEPAY_CREDS_PATH,
640
+ JSON.stringify({
641
+ agent_did: agentDid,
642
+ private_key: privateKey,
643
+ mnemonic: mnemonic || undefined,
644
+ api_url: options.apiUrl,
645
+ created_at: new Date().toISOString(),
646
+ }, null, 2)
647
+ );
648
+ console.log(chalk.green(' āœ“ Credentials saved to ~/.nervepay/credentials.json'));
649
+
650
+ // Update OpenClaw config if it exists
651
+ try {
652
+ const ocConfigPath = await findOpenClawConfigPath();
653
+ if (ocConfigPath) {
654
+ const existingConfig = JSON.parse(await readFile(ocConfigPath, 'utf-8'));
655
+ if (!existingConfig.plugins) existingConfig.plugins = {};
656
+ if (!existingConfig.plugins.entries) existingConfig.plugins.entries = {};
657
+ if (!existingConfig.plugins.entries.nervepay) {
658
+ existingConfig.plugins.entries.nervepay = { enabled: true, config: {} };
659
+ }
660
+ existingConfig.plugins.entries.nervepay.config = {
661
+ ...existingConfig.plugins.entries.nervepay.config,
662
+ apiUrl: options.apiUrl,
663
+ agentDid,
664
+ privateKey,
665
+ };
666
+ await writeFile(ocConfigPath, JSON.stringify(existingConfig, null, 2));
667
+ console.log(chalk.green(' āœ“ OpenClaw config updated'));
668
+ }
669
+ } catch {
670
+ // Non-fatal
671
+ }
672
+ } catch (e) {
673
+ console.log(chalk.yellow(' āš ļø Could not save credentials:'), e.message);
445
674
  }
675
+ }
446
676
 
447
- console.log(chalk.green('āœ“ Gateway found'));
448
- console.log(chalk.gray(' URL:'), gatewayUrl);
677
+ // Step 2: Read gateway config (from flags, env, or config files)
678
+ console.log(chalk.cyan('šŸ“” Reading gateway config...'));
449
679
 
450
- // Step 3: Complete pairing
451
- console.log(chalk.cyan('\nšŸ” Completing pairing...'));
452
- const client = new NervePayClient({
453
- apiUrl: options.apiUrl,
454
- agentDid,
455
- privateKey,
456
- });
680
+ let gatewayUrl = options.gatewayUrl;
681
+ let gatewayToken = options.gatewayToken;
457
682
 
458
- const result = await gateway.completePairing(client, {
459
- pairing_code: options.code,
460
- gateway_url: gatewayUrl,
461
- gateway_token: gatewayToken,
462
- gateway_name: options.name,
463
- });
683
+ // Try OpenClaw config if flags not provided
684
+ if (!gatewayUrl || !gatewayToken) {
685
+ const openclawConfig = await readOpenClawConfig();
686
+ const gw = extractGatewayConfig(openclawConfig);
687
+ gatewayUrl = gatewayUrl || gw.url;
688
+ gatewayToken = gatewayToken || gw.token;
689
+ }
464
690
 
465
- console.log(chalk.green('\nāœ… Pairing complete!'));
466
- console.log(chalk.gray(' Gateway ID:'), result.gateway_id || 'created');
467
- console.log(chalk.gray(' Agent DID: '), agentDid);
468
- console.log(chalk.gray('\n Your gateway is now live in the NervePay dashboard.'));
469
- console.log(chalk.gray(' Go to Mission Control to spawn agents and manage tasks.\n'));
470
- } catch (error) {
471
- console.error(chalk.red('\nāŒ Pairing failed:'), error.message);
691
+ if (!gatewayToken) {
692
+ console.error(chalk.red('\nāŒ Could not find gateway token'));
693
+ console.error(chalk.yellow(' Provide it via one of:'));
694
+ console.error(chalk.gray(' --gateway-token <token>'));
695
+ console.error(chalk.gray(' ~/.openclaw/openclaw.json (gateway.auth.token)'));
696
+ console.error(chalk.gray(' OPENCLAW_GATEWAY_TOKEN env var'));
472
697
  process.exit(1);
473
698
  }
474
- });
699
+
700
+ if (!gatewayUrl) {
701
+ console.error(chalk.red('\nāŒ Could not find gateway URL'));
702
+ console.error(chalk.yellow(' Provide it via one of:'));
703
+ console.error(chalk.gray(' --gateway-url <url> (e.g. ws://your-server:18789)'));
704
+ console.error(chalk.gray(' ~/.openclaw/openclaw.json'));
705
+ console.error(chalk.gray(' OPENCLAW_GATEWAY_URL env var'));
706
+ process.exit(1);
707
+ }
708
+
709
+ console.log(chalk.green('āœ“ Gateway found'));
710
+ console.log(chalk.gray(' URL:'), gatewayUrl);
711
+
712
+ // Step 3: Complete pairing
713
+ console.log(chalk.cyan('\nšŸ” Completing pairing...'));
714
+ const client = new NervePayClient({
715
+ apiUrl: options.apiUrl,
716
+ agentDid,
717
+ privateKey,
718
+ });
719
+
720
+ const result = await gateway.completePairing(client, {
721
+ pairing_code: options.code,
722
+ gateway_url: gatewayUrl,
723
+ gateway_token: gatewayToken,
724
+ gateway_name: options.name,
725
+ });
726
+
727
+ console.log(chalk.green('\nāœ… Pairing complete!'));
728
+ console.log(chalk.gray(' Gateway ID:'), result.gateway_id || 'created');
729
+ console.log(chalk.gray(' Agent DID: '), agentDid);
730
+ console.log(chalk.gray('\n Your gateway is now live in the NervePay dashboard.'));
731
+ console.log(chalk.gray(' Go to Mission Control to spawn agents and manage tasks.\n'));
732
+ } catch (error) {
733
+ console.error(chalk.red('\nāŒ Pairing failed:'), error.message);
734
+ process.exit(1);
735
+ }
736
+ }
475
737
 
476
738
  // ============================================================================
477
739
  // WHOAMI COMMAND
@@ -29,6 +29,12 @@ export interface CompletePairingParams {
29
29
  gateway_token: string;
30
30
  gateway_name: string;
31
31
  }
32
+ export interface DevicePairingCompleteParams {
33
+ device_token: string;
34
+ device_id: string;
35
+ gateway_url: string;
36
+ gateway_name?: string;
37
+ }
32
38
  export interface Gateway {
33
39
  id: string;
34
40
  name: string;
@@ -56,6 +62,13 @@ export declare function completePairing(client: NervePayClient, params: Complete
56
62
  gateway_id: string;
57
63
  status: string;
58
64
  }>;
65
+ /**
66
+ * Complete device node pairing — sends the scoped device token to NervePay API
67
+ */
68
+ export declare function completeDevicePairing(client: NervePayClient, params: DevicePairingCompleteParams): Promise<{
69
+ gateway_id: string;
70
+ status: string;
71
+ }>;
59
72
  /**
60
73
  * List all gateways
61
74
  */
@@ -1 +1 @@
1
- {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/tools/gateway.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/tools/gateway.ts"],"names":[],"mappings":"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"}
@@ -23,6 +23,12 @@ export async function getPairingRequestStatus(client, requestId) {
23
23
  export async function completePairing(client, params) {
24
24
  return client.post('/v1/integrations/openclaw/pairing/complete', params, true);
25
25
  }
26
+ /**
27
+ * Complete device node pairing — sends the scoped device token to NervePay API
28
+ */
29
+ export async function completeDevicePairing(client, params) {
30
+ return client.post('/v1/integrations/openclaw/device-pairing/complete', params, true);
31
+ }
26
32
  /**
27
33
  * List all gateways
28
34
  */
@@ -1 +1 @@
1
- {"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../src/tools/gateway.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../src/tools/gateway.ts"],"names":[],"mappings":"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"}
@@ -21,6 +21,21 @@ export declare function verifySignature(publicKeyBase58: string, payload: Record
21
21
  * Generate SHA-256 hash of string
22
22
  */
23
23
  export declare function sha256Hash(data: string): string;
24
+ /**
25
+ * Sign raw bytes with Ed25519 private key (for gateway challenge signing).
26
+ * Returns base64-encoded signature.
27
+ */
28
+ export declare function signRawBytes(privateKeyBase58: string, data: Uint8Array): Promise<string>;
29
+ /**
30
+ * Derive a deterministic device ID from a public key (SHA-256 hex fingerprint).
31
+ * Matches the Rust `derive_device_id()` implementation.
32
+ */
33
+ export declare function deriveDeviceId(publicKeyBase58: string): string;
34
+ /**
35
+ * Extract the Ed25519 public key from a private key seed.
36
+ * Returns base58-encoded public key.
37
+ */
38
+ export declare function getPublicKeyFromPrivate(privateKeyBase58: string): Promise<string>;
24
39
  /**
25
40
  * Generate random UUID v4
26
41
  */
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/utils/crypto.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CA6BpD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAwBtD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,gBAAgB,EAAE,MAAM,EACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/utils/crypto.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CA6BpD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAwBtD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,gBAAgB,EAAE,MAAM,EACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,gBAAgB,EAAE,MAAM,EACxB,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,MAAM,CAAC,CAMjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,CAAC,CAMjB;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
@@ -103,6 +103,36 @@ export function sha256Hash(data) {
103
103
  const bytes = new TextEncoder().encode(data);
104
104
  return bytesToHex(sha256(bytes));
105
105
  }
106
+ /**
107
+ * Sign raw bytes with Ed25519 private key (for gateway challenge signing).
108
+ * Returns base64-encoded signature.
109
+ */
110
+ export async function signRawBytes(privateKeyBase58, data) {
111
+ const keyStr = privateKeyBase58.replace(/^ed25519:/, '');
112
+ const privateKeyBytes = decodeBase58(keyStr);
113
+ const seed = privateKeyBytes.slice(0, 32);
114
+ const signature = await ed25519.sign(data, seed);
115
+ return Buffer.from(signature).toString('base64');
116
+ }
117
+ /**
118
+ * Derive a deterministic device ID from a public key (SHA-256 hex fingerprint).
119
+ * Matches the Rust `derive_device_id()` implementation.
120
+ */
121
+ export function deriveDeviceId(publicKeyBase58) {
122
+ const publicKeyBytes = decodeBase58(publicKeyBase58);
123
+ return bytesToHex(sha256(publicKeyBytes));
124
+ }
125
+ /**
126
+ * Extract the Ed25519 public key from a private key seed.
127
+ * Returns base58-encoded public key.
128
+ */
129
+ export async function getPublicKeyFromPrivate(privateKeyBase58) {
130
+ const keyStr = privateKeyBase58.replace(/^ed25519:/, '');
131
+ const privateKeyBytes = decodeBase58(keyStr);
132
+ const seed = privateKeyBytes.slice(0, 32);
133
+ const publicKey = await ed25519.getPublicKey(seed);
134
+ return encodeBase58(publicKey);
135
+ }
106
136
  /**
107
137
  * Generate random UUID v4
108
138
  */
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/utils/crypto.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/utils/crypto.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nervepay",
3
- "version": "1.2.1",
3
+ "version": "1.2.8",
4
4
  "description": "NervePay plugin for OpenClaw - Self-sovereign identity, vault, and orchestration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -43,13 +43,15 @@
43
43
  "commander": "^13.1.0",
44
44
  "inquirer": "^12.4.0",
45
45
  "chalk": "^5.4.1",
46
- "open": "^10.1.0"
46
+ "open": "^10.1.0",
47
+ "ws": "^8.16.0"
47
48
  },
48
49
  "peerDependencies": {
49
50
  "openclaw": ">=1.0.0"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@types/node": "^22.13.0",
54
+ "@types/ws": "^8.5.10",
53
55
  "typescript": "^5.7.3",
54
56
  "vitest": "^3.0.0"
55
57
  },