decharge-scout 4.0.5 → 4.3.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 (3) hide show
  1. package/.env.example +5 -0
  2. package/index.js +135 -101
  3. package/package.json +1 -1
package/.env.example CHANGED
@@ -27,3 +27,8 @@ STAKE_AMOUNT=0.01
27
27
 
28
28
  # Premium Feature Price (in SOL)
29
29
  PREMIUM_PRICE=0.001
30
+
31
+ # Query Cycle Interval (in minutes)
32
+ # How often to fetch weather & submit data (default: 15)
33
+ # For testing, you can set to 2 minutes: CYCLE_INTERVAL_MINUTES=2
34
+ CYCLE_INTERVAL_MINUTES=15
package/index.js CHANGED
@@ -40,14 +40,15 @@ import { submitToOracle } from './src/oracle.js';
40
40
  import { initializePoints, awardPoints, getPoints, savePoints } from './src/points.js';
41
41
  import { getLocation } from './src/geolocation.js';
42
42
  import { purchasePremiumData } from './src/x402.js';
43
- import { hasBeenAskedForAlpha, markAskedForAlpha, parseAlphaContribution, saveAlphaContribution, calculateAlphaBonus, getAlphaInsights, verifyContribution, getInformationSources } from './src/local-alpha.js';
43
+ import { parseAlphaContribution, saveAlphaContribution, calculateAlphaBonus, getAlphaInsights, verifyContribution, getInformationSources } from './src/local-alpha.js';
44
44
 
45
45
  const __filename = fileURLToPath(import.meta.url);
46
46
  const __dirname = dirname(__filename);
47
47
 
48
48
  // Configuration
49
49
  const STAKE_AMOUNT = parseFloat(process.env.STAKE_AMOUNT || '0.01');
50
- const CYCLE_INTERVAL_MS = 15 * 60 * 1000; // 15 minutes
50
+ const CYCLE_INTERVAL_MINUTES = parseInt(process.env.CYCLE_INTERVAL_MINUTES || '15'); // Default: 15 minutes
51
+ const CYCLE_INTERVAL_MS = CYCLE_INTERVAL_MINUTES * 60 * 1000;
51
52
 
52
53
  // Global state
53
54
  let isRunning = true;
@@ -353,17 +354,147 @@ async function runQueryCycle(wallet, agentName, location, options) {
353
354
  }
354
355
  }
355
356
 
356
- // Prepare submission data
357
+ // Ask for special notes before submission (with 10s timeout)
358
+ console.log(chalk.cyan('\n💬 Add special notes to this submission? (optional)'));
359
+ console.log(chalk.gray(' Examples: "High AC usage today", "Local festival", "Grid maintenance"\n'));
360
+ console.log(chalk.gray(' (Will auto-submit in 10 seconds if no input)\n'));
361
+
362
+ const specialNotes = await Promise.race([
363
+ question(chalk.blue('Special notes (or press Enter to skip): ')),
364
+ new Promise((resolve) => {
365
+ setTimeout(() => {
366
+ console.log(chalk.yellow('\n⏱️ Timeout - submitting without notes'));
367
+ resolve('');
368
+ }, 10000); // 10 second timeout
369
+ })
370
+ ]);
371
+
372
+ // Local Alpha Contribution - Ask BEFORE every submission for bonus points
373
+ console.log(chalk.cyan('\n💡 Bonus Points: Share Local Peak Time Knowledge!'));
374
+ console.log(chalk.gray(' Help improve global energy data by sharing when electricity is expensive/cheap in your area.\n'));
375
+
376
+ console.log(chalk.blue('💬 Examples:'));
377
+ console.log(chalk.gray(' • "7-9PM peak in Lagos" (evening peak)'));
378
+ console.log(chalk.gray(' • "1-5AM cheap in Berlin" (off-peak)'));
379
+ console.log(chalk.gray(' • "5-8PM peak in Mumbai" (dinner time surge)'));
380
+ console.log(chalk.gray(' • "2-6AM cheap in Texas" (wind energy overnight)'));
381
+ console.log(chalk.gray(' (Will auto-skip in 15 seconds if no input)\n'));
382
+
383
+ const alphaInput = await Promise.race([
384
+ question(chalk.blue('Share local peak times (or press Enter to skip): ')),
385
+ new Promise((resolve) => {
386
+ setTimeout(() => {
387
+ console.log(chalk.yellow('\n⏱️ Timeout - skipping bonus contribution'));
388
+ resolve('');
389
+ }, 15000); // 15 second timeout
390
+ })
391
+ ]);
392
+
393
+ // Process alpha contribution if provided
394
+ if (alphaInput.trim()) {
395
+ const parsed = parseAlphaContribution(alphaInput, location);
396
+ if (parsed) {
397
+ // Verify contribution against current pricing data
398
+ const verification = verifyContribution(parsed, energyData);
399
+
400
+ // Save contribution with verification status
401
+ const contribution = saveAlphaContribution(parsed, agentName, location, verification);
402
+
403
+ // Store for dashboard submission
404
+ pendingAlphaContribution = {
405
+ type: parsed.type,
406
+ startHour: parsed.startHour,
407
+ endHour: parsed.endHour,
408
+ location: parsed.location,
409
+ verified: verification.verified,
410
+ confidence: verification.confidence,
411
+ verificationReasons: verification.reasons
412
+ };
413
+
414
+ // Calculate bonus (higher for verified contributions)
415
+ const alphaBonus = calculateAlphaBonus(parsed, verification);
416
+
417
+ awardPoints(wallet, alphaBonus);
418
+
419
+ console.log(chalk.green(`\n✅ Thanks for contributing! Earned ${alphaBonus} bonus points!`));
420
+ console.log(chalk.gray(` Contribution: ${parsed.type} hours ${parsed.startHour}-${parsed.endHour} in ${parsed.location}`));
421
+
422
+ // Show verification results
423
+ if (verification.verified) {
424
+ console.log(chalk.green(` 🎯 Verified! Confidence: ${(verification.confidence * 100).toFixed(0)}%`));
425
+ verification.reasons.forEach(reason => {
426
+ console.log(chalk.gray(` ${reason}`));
427
+ });
428
+ console.log(chalk.green(` +${alphaBonus - 10} extra points for verified contribution!`));
429
+ } else {
430
+ console.log(chalk.yellow(` ⚠️ Low confidence: ${(verification.confidence * 100).toFixed(0)}%`));
431
+ verification.reasons.forEach(reason => {
432
+ console.log(chalk.gray(` ${reason}`));
433
+ });
434
+ console.log(chalk.gray(` Tip: Contributions that match actual price patterns earn more points!`));
435
+ }
436
+ } else {
437
+ console.log(chalk.yellow('⚠️ Could not parse contribution.'));
438
+ console.log(chalk.gray(' Accepted formats:'));
439
+ console.log(chalk.gray(' • "7-9PM peak in Lagos"'));
440
+ console.log(chalk.gray(' • "1-5AM cheap in Berlin"'));
441
+ console.log(chalk.gray(' • "19-21 peak Mumbai" (24-hour format also works)'));
442
+ }
443
+ }
444
+
445
+ // Prepare comprehensive submission data
357
446
  const submissionData = {
358
447
  agent_name: agentName,
359
448
  location: location,
360
449
  timestamp: Date.now(),
450
+
451
+ // Summary results (for quick display)
361
452
  results: {
362
453
  cheapest_window: cheapestWindow.timeWindow,
363
454
  price: cheapestWindow.price,
364
455
  savings: savings,
365
456
  data_points: energyData.length
366
- }
457
+ },
458
+
459
+ // Full weather data
460
+ weather: {
461
+ location: weatherData.location,
462
+ forecast_summary: {
463
+ hours: weatherData.forecast.length,
464
+ temp_range: {
465
+ min: Math.min(...weatherData.forecast.map(f => f.temperature)),
466
+ max: Math.max(...weatherData.forecast.map(f => f.temperature))
467
+ },
468
+ avg_wind: weatherData.forecast.reduce((sum, f) => sum + f.windSpeed, 0) / weatherData.forecast.length,
469
+ avg_solar: weatherData.forecast.reduce((sum, f) => sum + f.solarRadiation, 0) / weatherData.forecast.length
470
+ },
471
+ optimal_hour_conditions: cheapestHourData?.weather || null
472
+ },
473
+
474
+ // Pricing insights
475
+ pricing: {
476
+ region: insights.region,
477
+ base_price: insights.basePrice,
478
+ price_range: {
479
+ min: insights.minPrice,
480
+ max: insights.maxPrice,
481
+ variation_percent: insights.priceRange
482
+ },
483
+ savings_potential: insights.savingsPotential,
484
+ country_code: countryCode
485
+ },
486
+
487
+ // Optimization details
488
+ optimization: {
489
+ cheapest_hour: cheapestWindow.hour,
490
+ time_window: cheapestWindow.timeWindow,
491
+ price: cheapestWindow.price,
492
+ savings_percent: savings,
493
+ reasons: cheapestHourData?.reasons || []
494
+ },
495
+
496
+ // Special notes from user
497
+ notes: specialNotes.trim() || null
367
498
  };
368
499
 
369
500
  // Submit to oracle
@@ -434,103 +565,6 @@ async function runQueryCycle(wallet, agentName, location, options) {
434
565
  console.log(chalk.magenta(`\n⭐ Earned ${totalPointsEarned} points! (${basePoints} base${bonusPoints > 0 ? ` + ${bonusPoints} bonus` : ''})`));
435
566
  console.log(chalk.magenta(`⭐ Total Points: ${currentPoints}`));
436
567
 
437
- // Local Alpha Contribution (ask once after first run)
438
- if (totalRuns === 1 && !hasBeenAskedForAlpha()) {
439
- console.log(chalk.cyan('\n💡 Local Alpha Contribution - Help Improve Global Energy Data!'));
440
- console.log(chalk.gray(' Share your local electricity peak time knowledge for bonus points.\n'));
441
-
442
- // Show where to find this information
443
- console.log(chalk.blue('📚 Where to find peak time information:'));
444
- const sources = getInformationSources(location);
445
-
446
- // General sources
447
- sources.general.forEach(source => {
448
- console.log(chalk.gray(` ${source}`));
449
- });
450
-
451
- // Region-specific sources
452
- const regionKeys = Object.keys(sources.byRegion);
453
- if (regionKeys.length > 0) {
454
- console.log(chalk.blue('\n📍 For your region:'));
455
- regionKeys.forEach(region => {
456
- sources.byRegion[region].forEach(source => {
457
- console.log(chalk.gray(` ${source}`));
458
- });
459
- });
460
- }
461
-
462
- console.log(chalk.blue('\n💬 Examples of good contributions:'));
463
- console.log(chalk.gray(' • "7-9PM peak in Lagos" (evening peak)'));
464
- console.log(chalk.gray(' • "1-5AM cheap in Berlin" (off-peak)'));
465
- console.log(chalk.gray(' • "5-8PM peak in Mumbai" (dinner time surge)'));
466
- console.log(chalk.gray(' • "2-6AM cheap in Texas" (wind energy overnight)'));
467
- console.log(chalk.gray(' (Will auto-skip in 15 seconds if no input)\n'));
468
-
469
- // Add timeout to prevent hanging
470
- const alphaInput = await Promise.race([
471
- question(chalk.blue('Share local peak times (or press Enter to skip): ')),
472
- new Promise((resolve) => {
473
- setTimeout(() => {
474
- console.log(chalk.yellow('\n⏱️ Timeout - skipping alpha contribution'));
475
- resolve('');
476
- }, 15000); // 15 second timeout
477
- })
478
- ]);
479
-
480
- if (alphaInput.trim()) {
481
- const parsed = parseAlphaContribution(alphaInput, location);
482
- if (parsed) {
483
- // Verify contribution against current pricing data
484
- const verification = verifyContribution(parsed, energyData);
485
-
486
- // Save contribution with verification status
487
- const contribution = saveAlphaContribution(parsed, agentName, location, verification);
488
-
489
- // Store for dashboard submission
490
- pendingAlphaContribution = {
491
- type: parsed.type,
492
- startHour: parsed.startHour,
493
- endHour: parsed.endHour,
494
- location: parsed.location,
495
- verified: verification.verified,
496
- confidence: verification.confidence,
497
- verificationReasons: verification.reasons
498
- };
499
-
500
- // Calculate bonus (higher for verified contributions)
501
- const alphaBonus = calculateAlphaBonus(parsed, verification);
502
-
503
- awardPoints(wallet, alphaBonus);
504
-
505
- console.log(chalk.green(`\n✅ Thanks for contributing! Earned ${alphaBonus} bonus points!`));
506
- console.log(chalk.gray(` Contribution: ${parsed.type} hours ${parsed.startHour}-${parsed.endHour} in ${parsed.location}`));
507
-
508
- // Show verification results
509
- if (verification.verified) {
510
- console.log(chalk.green(` 🎯 Verified! Confidence: ${(verification.confidence * 100).toFixed(0)}%`));
511
- verification.reasons.forEach(reason => {
512
- console.log(chalk.gray(` ${reason}`));
513
- });
514
- console.log(chalk.green(` +${alphaBonus - 10} extra points for verified contribution!`));
515
- } else {
516
- console.log(chalk.yellow(` ⚠️ Low confidence: ${(verification.confidence * 100).toFixed(0)}%`));
517
- verification.reasons.forEach(reason => {
518
- console.log(chalk.gray(` ${reason}`));
519
- });
520
- console.log(chalk.gray(` Tip: Contributions that match actual price patterns earn more points!`));
521
- }
522
- } else {
523
- console.log(chalk.yellow('⚠️ Could not parse contribution.'));
524
- console.log(chalk.gray(' Accepted formats:'));
525
- console.log(chalk.gray(' • "7-9PM peak in Lagos"'));
526
- console.log(chalk.gray(' • "1-5AM cheap in Berlin"'));
527
- console.log(chalk.gray(' • "19-21 peak Mumbai" (24-hour format also works)'));
528
- }
529
- }
530
-
531
- markAskedForAlpha();
532
- }
533
-
534
568
  // Show alpha insights if available
535
569
  if (totalRuns === 1) {
536
570
  const alphaInsights = getAlphaInsights(location);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "decharge-scout",
3
- "version": "4.0.5",
3
+ "version": "4.3.0",
4
4
  "description": "Global Energy Scout - Weather-powered intelligent energy price forecasting with Solana integration",
5
5
  "main": "index.js",
6
6
  "type": "module",