@glowlabs-org/utils 0.1.3 → 0.1.5

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.
@@ -14,7 +14,7 @@ export type CreateWeeklyReportArgs = {
14
14
  gcaUrls: string[];
15
15
  apiUrl: string;
16
16
  };
17
- export declare function createWeeklyReport({ week, gcaUrls, apiUrl, }: CreateWeeklyReportArgs): Promise<{
17
+ export declare function createWeeklyReportLegacy(args: CreateWeeklyReportArgs): Promise<{
18
18
  headlineStats: {
19
19
  weekNumber: number;
20
20
  totalCreditsProduced: string;
@@ -36,7 +36,8 @@ export declare function createWeeklyReport({ week, gcaUrls, apiUrl, }: CreateWee
36
36
  }[];
37
37
  farms: import("./types").Farm[];
38
38
  rawData: import("./types").GCAServerResponse;
39
- } | {
39
+ }>;
40
+ export declare function createWeeklyReport({ week, gcaUrls, apiUrl, }: CreateWeeklyReportArgs): Promise<{
40
41
  headlineStats: {
41
42
  weekNumber: number;
42
43
  totalCreditsProduced: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glowlabs-org/utils",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "A library containing all typechain types and addresses relating to the glow guarded launch",
5
5
  "keywords": [],
6
6
  "author": "",
@@ -42,6 +42,7 @@
42
42
  },
43
43
  "scripts": {
44
44
  "test": "echo \"Error: no test specified\" && exit 1",
45
- "build": "rollup -c"
45
+ "build": "rollup -c",
46
+ "start": "ts-node scripts/index.ts"
46
47
  }
47
48
  }
package/src/index.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  export * from "./lib/create-weekly-report/types/index";
2
2
  export * from "./constants/index";
3
- export { createWeeklyReport } from "./lib/create-weekly-report/index";
3
+ export {
4
+ createWeeklyReport,
5
+ createWeeklyReportLegacy,
6
+ } from "./lib/create-weekly-report/index";
@@ -39,7 +39,7 @@ export type CreateWeeklyReportArgs = {
39
39
  apiUrl: string;
40
40
  };
41
41
 
42
- async function createWeeklyReportLegacy(args: CreateWeeklyReportArgs) {
42
+ export async function createWeeklyReportLegacy(args: CreateWeeklyReportArgs) {
43
43
  const mapLegacy = new Map<string, MerkleLeafIntermediary>();
44
44
 
45
45
  function addValueToMapLegacy(
@@ -149,11 +149,6 @@ async function createWeeklyReportLegacy(args: CreateWeeklyReportArgs) {
149
149
  usdgWeight <= 0 &&
150
150
  rewardSplit.usdgSplitPercent > 0
151
151
  ) {
152
- console.log(
153
- farm.carbonCreditsProduced,
154
- usdgWeight,
155
- rewardSplit.usdgSplitPercent
156
- );
157
152
  throw new Error(
158
153
  "USDG weight is less than 0 and carbon credits produced is greater than 0"
159
154
  );
@@ -163,11 +158,6 @@ async function createWeeklyReportLegacy(args: CreateWeeklyReportArgs) {
163
158
  glowWeight <= 0 &&
164
159
  rewardSplit.glowSplitPercent > 0
165
160
  ) {
166
- console.log(
167
- farm.weeklyPayment,
168
- glowWeight,
169
- rewardSplit.glowSplitPercent
170
- );
171
161
  throw new Error(
172
162
  "Glow weight is less than 0 and weekly payment is greater than 0"
173
163
  );
@@ -178,11 +168,6 @@ async function createWeeklyReportLegacy(args: CreateWeeklyReportArgs) {
178
168
  usdgWeight <= 0 &&
179
169
  rewardSplit.usdgSplitPercent > 0
180
170
  ) {
181
- console.log(
182
- farm.carbonCreditsProduced,
183
- usdgWeight.toString(),
184
- rewardSplit.usdgSplitPercent
185
- );
186
171
  throw new Error(
187
172
  `USDG weight is less than or equal to 0 and carbon credits produced is greater than 0 for farm ${farm.shortId}`
188
173
  );
@@ -192,11 +177,6 @@ async function createWeeklyReportLegacy(args: CreateWeeklyReportArgs) {
192
177
  glowWeight <= 0 &&
193
178
  rewardSplit.glowSplitPercent > 0
194
179
  ) {
195
- console.log(
196
- farm.weeklyPayment,
197
- glowWeight.toString(),
198
- rewardSplit.glowSplitPercent
199
- );
200
180
  throw new Error(
201
181
  `Glow weight is less than or equal to 0 and weekly payment is greater than 0 for farm ${farm.shortId}`
202
182
  );
@@ -372,12 +352,9 @@ export async function createWeeklyReport({
372
352
  gcaUrls,
373
353
  apiUrl,
374
354
  }: CreateWeeklyReportArgs) {
375
- if (week < 72) {
376
- return createWeeklyReportLegacy({ week, gcaUrls, apiUrl });
377
- }
378
-
379
355
  const map = new Map<string, MerkleLeaf>();
380
356
 
357
+ // Fetch active farms for the week (source of truth) and audits for the week.
381
358
  const [apiResponse, auditsRes] = await Promise.all([
382
359
  fetchFarmsForWeek(week, gcaUrls, apiUrl),
383
360
  axios.get<Audit[]>(
@@ -385,38 +362,119 @@ export async function createWeeklyReport({
385
362
  ),
386
363
  ]);
387
364
 
388
- const farms = apiResponse.filteredFarms;
389
- const audits = auditsRes.data;
365
+ const farms = apiResponse.filteredFarms; // List of farms active this week.
366
+ const audits = auditsRes.data; // Audits potentially containing adjusted credits.
390
367
  const rawData = apiResponse.rawData;
391
368
 
369
+ // Map to store the final adjusted credit (as bigint) for each active farm shortId.
392
370
  const shortIdToAdjustedCredit = new Map<string, bigint>();
371
+ // Set to track shortIds that have been assigned a credit from a valid audit to prevent duplicates.
372
+ const processedAuditShortIds = new Set<string>();
373
+ // Set of shortIds from the active farms list for quick lookup.
374
+ const farmShortIds = new Set(farms.map((f) => String(f.shortId)));
393
375
 
376
+ // Process each audit to extract adjusted credit values for active farms.
394
377
  for (const audit of audits) {
395
378
  const activeShortIds = audit.activeShortIds ?? [];
396
379
  const adjustedCredit =
397
380
  audit.summary?.carbonFootprintAndProduction?.adjustedWeeklyCarbonCredit?.trim();
398
381
 
382
+ // Basic validation: Ensure the audit has a valid numeric credit and lists associated shortIds.
399
383
  if (!adjustedCredit || !NUMERIC_REGEX.test(adjustedCredit))
400
384
  throw new Error(
401
385
  `Invalid adjustedWeeklyCarbonCredit for audit ${audit.id}`
402
386
  );
403
387
  if (activeShortIds.length === 0)
404
- throw new Error(`audit ${audit.id} has empty activeShortIds`);
388
+ throw new Error(`Audit ${audit.id} has empty activeShortIds`);
389
+
390
+ // Separate the shortIds listed in the audit into those that are active this week and those that are not.
391
+ const auditActiveFarmSids: string[] = [];
392
+ const auditInactiveFarmSids: string[] = [];
393
+ for (const sid of activeShortIds) {
394
+ const sidString = String(sid);
395
+ if (farmShortIds.has(sidString)) {
396
+ auditActiveFarmSids.push(sidString);
397
+ } else {
398
+ auditInactiveFarmSids.push(sidString);
399
+ }
400
+ }
401
+
402
+ // --- Audit Validity Checks ---
405
403
 
406
- const splitValue = new Decimal(adjustedCredit).div(activeShortIds.length);
404
+ // Data Integrity Check: An audit for credit distribution should not mix active and inactive farms for the current week.
405
+ if (auditActiveFarmSids.length > 0 && auditInactiveFarmSids.length > 0) {
406
+ throw new Error(
407
+ `Audit ${
408
+ audit.id
409
+ } for week ${week} contains a mix of active farms (${auditActiveFarmSids.join(
410
+ ", "
411
+ )}) and inactive farms (${auditInactiveFarmSids.join(
412
+ ", "
413
+ )}). Audits should only contain active farms when distributing credits.`
414
+ );
415
+ }
416
+
417
+ // Skip Audit: If the audit only contains shortIds that are not active this week, it's irrelevant for this report.
418
+ if (auditActiveFarmSids.length === 0) {
419
+ continue; // Move to the next audit.
420
+ }
421
+
422
+ // --- Process Valid Audit for Active Farms ---
423
+
424
+ // Calculate the credit share per active farm within this audit.
425
+ const splitValue = new Decimal(adjustedCredit).div(
426
+ auditActiveFarmSids.length // Divide only by the count of *active* farms found in this audit.
427
+ );
428
+
429
+ // Sanity Check: Ensure the calculated split is not zero.
407
430
  if (splitValue.isZero())
408
431
  throw new Error(
409
- `Zero adjustedWeeklyCarbonCredit split in audit ${audit.id}`
432
+ `Zero adjustedWeeklyCarbonCredit split for active farms in audit ${audit.id}`
410
433
  );
411
434
 
435
+ // Convert the decimal split value to a bigint using the defined precision.
412
436
  const splitBigInt = toBigInt(splitValue, USDG_WEIGHT_DECIMAL_PRECISION);
413
- for (const sid of activeShortIds)
414
- shortIdToAdjustedCredit.set(String(sid), splitBigInt);
437
+
438
+ // Dust Check: Ensure that the conversion to bigint didn't truncate the value to zero.
439
+ if (splitBigInt === BigInt(0)) {
440
+ throw new Error(
441
+ `Adjusted credit split for audit ${
442
+ audit.id
443
+ } resulted in zero BigInt after conversion for precision ${USDG_WEIGHT_DECIMAL_PRECISION}. Original split value: ${splitValue.toString()}. This might indicate dust loss.`
444
+ );
445
+ }
446
+
447
+ // Distribute the calculated split value to each active farm associated with this audit.
448
+ for (const sidString of auditActiveFarmSids) {
449
+ // Duplicate Check: Ensure this shortId hasn't already received credit from another valid audit this week.
450
+ if (processedAuditShortIds.has(sidString)) {
451
+ throw new Error(
452
+ `ShortId ${sidString} found in multiple valid audits for week ${week}`
453
+ );
454
+ }
455
+ processedAuditShortIds.add(sidString); // Mark this shortId as processed.
456
+
457
+ // Store the adjusted credit for this active farm.
458
+ shortIdToAdjustedCredit.set(sidString, splitBigInt);
459
+ }
460
+ } // End of loop through audits.
461
+
462
+ // Final Validation: Ensure every farm considered active for this week received an adjusted credit value from a valid audit.
463
+ for (const farmId of farmShortIds) {
464
+ if (!shortIdToAdjustedCredit.has(farmId)) {
465
+ throw new Error(
466
+ `Farm ${farmId} is active for week ${week} but has no corresponding adjusted credit found in any valid audit.`
467
+ );
468
+ }
415
469
  }
416
470
 
417
- let totalCreditsProduced18dp = BigInt(0);
471
+ // --- Start Calculation of Merkle Tree Weights ---
418
472
 
473
+ let totalCreditsProduced18dp = BigInt(0); // Raw total from farm data, for reporting/comparison.
474
+
475
+ // Iterate through each active farm to calculate its contribution to the Merkle tree leaves.
419
476
  for (const farm of farms) {
477
+ // Basic checks for farm data consistency.
420
478
  if (farm.status === "Unassigned") {
421
479
  throw new Error(`farm ${farm.shortId} is unassigned`);
422
480
  }
@@ -433,11 +491,13 @@ export async function createWeeklyReport({
433
491
  );
434
492
  }
435
493
 
494
+ // Accumulate the reported carbon credits (18 decimal places).
436
495
  totalCreditsProduced18dp += parseUnits(
437
496
  customToFixed(farm.carbonCreditsProduced, 18),
438
497
  18
439
498
  );
440
499
 
500
+ // Validate reward split percentages add up to 1 (within tolerance).
441
501
  const sumGlow = farm.rewardSplits.reduce(
442
502
  (acc: number, r: any) => acc + r.glowSplitPercent,
443
503
  0
@@ -452,49 +512,62 @@ export async function createWeeklyReport({
452
512
  if (Math.abs(sumUSDG - 1) > percentTolerance)
453
513
  throw new Error(`USDG splits ≠1 for farm ${farm.shortId}`);
454
514
 
515
+ // Get the base GLOW payment for the farm, converted to bigint with appropriate precision.
455
516
  const glowBase = parseUnits(
456
517
  customToFixed(farm.weeklyPayment, GLOW_WEIGHT_DECIMAL_PRECISION),
457
518
  GLOW_WEIGHT_DECIMAL_PRECISION
458
519
  );
459
520
 
521
+ // Retrieve the pre-calculated adjusted credit for this farm. Should always exist due to prior checks.
460
522
  const adjustedCreditBigInt =
461
523
  shortIdToAdjustedCredit.get(String(farm.shortId)) ?? BigInt(0);
462
524
 
525
+ // Sanity check (likely redundant due to earlier checks, but safe).
463
526
  if (adjustedCreditBigInt <= BigInt(0))
464
527
  throw new Error(
465
528
  `Adjusted credit is less than or equal to 0 for farm ${farm.shortId}`
466
529
  );
467
530
 
531
+ // Process each reward split recipient for this farm.
468
532
  for (const split of farm.rewardSplits) {
533
+ // Calculate the GLOW weight for this recipient based on the farm's weekly payment and split percentage.
469
534
  const glowWeight = multiplyBigIntByDecimalPercentage(
470
535
  glowBase,
471
536
  GLOW_WEIGHT_DECIMAL_PRECISION,
472
537
  split.glowSplitPercent
473
538
  );
539
+ // Calculate the USDG weight for this recipient based on the farm's *adjusted* credit and split percentage.
474
540
  const usdgWeight = multiplyBigIntByDecimalPercentage(
475
541
  adjustedCreditBigInt,
476
542
  USDG_WEIGHT_DECIMAL_PRECISION,
477
543
  split.usdgSplitPercent
478
544
  );
479
545
 
546
+ // Dust Loss Checks: Ensure non-zero percentages didn't result in zero weight due to precision limits.
480
547
  if (
481
548
  split.usdgSplitPercent > 0 &&
482
549
  adjustedCreditBigInt > BigInt(0) &&
483
550
  usdgWeight === BigInt(0)
484
551
  )
485
- throw new Error(`USDG dust lost for farm ${farm.shortId}`);
552
+ throw new Error(
553
+ `USDG dust lost for farm ${farm.shortId} wallet ${split.walletAddress}`
554
+ );
486
555
  if (
487
556
  split.glowSplitPercent > 0 &&
488
557
  glowBase > BigInt(0) &&
489
558
  glowWeight === BigInt(0)
490
559
  )
491
- throw new Error(`Glow dust lost for farm ${farm.shortId}`);
560
+ throw new Error(
561
+ `Glow dust lost for farm ${farm.shortId} wallet ${split.walletAddress}`
562
+ );
492
563
 
564
+ // Overflow Check: Ensure individual leaf weights don't exceed the maximum allowed.
493
565
  if (glowWeight > MAX_WEIGHT || usdgWeight > MAX_WEIGHT)
494
566
  throw new Error(
495
567
  `Leaf weight overflow on wallet ${split.walletAddress}`
496
568
  );
497
569
 
570
+ // Accumulate the calculated weights into the map for the recipient wallet.
498
571
  accumulateLeafWeights(
499
572
  split.walletAddress,
500
573
  { wallet: split.walletAddress, glowWeight, usdgWeight },
@@ -503,27 +576,33 @@ export async function createWeeklyReport({
503
576
  }
504
577
  }
505
578
 
579
+ // --- Finalize Merkle Tree and Generate Report Data ---
580
+
581
+ // Convert the accumulated weights map into the final list of leaves for the tree.
506
582
  const finalizedLeaves: FinalizedLeaf[] = Array.from(map.values()).map(
507
583
  ({ wallet, glowWeight, usdgWeight }) => ({
508
584
  wallet,
509
- glowWeight: glowWeight.toString(),
585
+ glowWeight: glowWeight.toString(), // Convert BigInts to strings for hashing/reporting.
510
586
  usdgWeight: usdgWeight.toString(),
511
587
  })
512
588
  );
513
589
 
590
+ // Hash each leaf according to the defined structure.
514
591
  const hashedLeaves = finalizedLeaves.map((leaf) =>
515
592
  hashLeaf({
516
593
  address: leaf.wallet,
517
594
  glowWeight: leaf.glowWeight,
518
- usdcWeight: leaf.usdgWeight,
595
+ usdcWeight: leaf.usdgWeight, // Note: Parameter name inconsistency (usdc vs usdg)
519
596
  })
520
597
  );
521
598
 
599
+ // Build the Merkle tree.
522
600
  const merkleTree = new MerkleTree(hashedLeaves, ethers.utils.keccak256, {
523
- sort: true,
601
+ sort: true, // Ensure consistent tree structure.
524
602
  });
525
- const merkleRoot = merkleTree.getHexRoot();
603
+ const merkleRoot = merkleTree.getHexRoot(); // Get the root hash.
526
604
 
605
+ // Calculate the total weights across all finalized leaves.
527
606
  const totalGlowWeight = finalizedLeaves.reduce(
528
607
  (acc, { glowWeight }) => acc.add(glowWeight),
529
608
  ethers.BigNumber.from(0)
@@ -533,23 +612,29 @@ export async function createWeeklyReport({
533
612
  ethers.BigNumber.from(0)
534
613
  );
535
614
 
615
+ // Total Weight Overflow Checks: Ensure sums don't exceed maximum.
536
616
  if (totalGlowWeight.toBigInt() > MAX_WEIGHT)
537
617
  throw new Error("Total glow weight overflow");
538
618
  if (totalUSDGWeight.toBigInt() > MAX_WEIGHT)
539
619
  throw new Error("Total USDG weight overflow");
540
620
 
621
+ // Generate Merkle proofs for each leaf and verify them.
541
622
  const leavesWithProofs = finalizedLeaves.map((leaf) => {
542
623
  const hashed = hashLeaf({
543
624
  address: leaf.wallet,
544
625
  glowWeight: leaf.glowWeight,
545
- usdcWeight: leaf.usdgWeight,
626
+ usdcWeight: leaf.usdgWeight, // Note: Parameter name inconsistency
546
627
  });
547
628
  const proof = merkleTree.getHexProof(hashed);
548
629
  if (!merkleTree.verify(proof, hashed, merkleRoot))
630
+ // Verify proof against the calculated root.
549
631
  throw new Error("Invalid proof for " + leaf.wallet);
550
632
  return { ...leaf, proof };
551
633
  });
552
634
 
635
+ // --- Sanity Checks on Final Weights ---
636
+
637
+ // Verify that summing weights from leavesWithProofs matches the earlier reduce calculation.
553
638
  const glowSumProofLoop = leavesWithProofs.reduce(
554
639
  (acc, l) => acc.add(l.glowWeight),
555
640
  ethers.BigNumber.from(0)
@@ -572,22 +657,25 @@ export async function createWeeklyReport({
572
657
  throw new Error("USDG sum mismatch");
573
658
  }
574
659
 
660
+ // Calculate the total expected credits based on the adjusted values used.
575
661
  const totalExpectedCredits = farms.reduce((acc: Decimal, f: any) => {
576
662
  const adj = shortIdToAdjustedCredit.get(String(f.shortId)) ?? BigInt(0);
577
663
  return acc.plus(fromBigInt(adj, USDG_WEIGHT_DECIMAL_PRECISION));
578
664
  }, new Decimal(0));
579
665
 
666
+ // Convert total USDG weight back to human-readable decimal for deviation check.
580
667
  const totalUSDGWeightHuman = new Decimal(
581
668
  formatUnits(
582
669
  BigInt(totalUSDGWeight.toString()),
583
670
  USDG_WEIGHT_DECIMAL_PRECISION
584
671
  )
585
672
  );
673
+ // Check deviation between total adjusted credits used and the final sum of USDG weights.
586
674
  if (
587
675
  greaterThanMaxDeviation(
588
676
  totalExpectedCredits.toNumber(),
589
677
  totalUSDGWeightHuman.toNumber(),
590
- 0.001
678
+ 0.001 // 0.1% tolerance
591
679
  )
592
680
  ) {
593
681
  console.error(
@@ -599,21 +687,24 @@ export async function createWeeklyReport({
599
687
  throw new Error("totalExpectedCredits vs USDG weight deviation >0.1% ");
600
688
  }
601
689
 
690
+ // Convert total Glow weight back to human-readable decimal.
602
691
  const totalGlowWeightHuman = new Decimal(
603
692
  formatUnits(
604
693
  BigInt(totalGlowWeight.toString()),
605
694
  GLOW_WEIGHT_DECIMAL_PRECISION
606
695
  )
607
696
  );
697
+ // Sum the original weekly protocol fee payments from farm data.
608
698
  const totalProtocolFeePayments = farms.reduce(
609
699
  (acc: number, f: any) => acc + f.weeklyPayment,
610
700
  0
611
701
  );
702
+ // Check deviation between total glow weight and total protocol fees paid.
612
703
  if (
613
704
  greaterThanMaxDeviation(
614
705
  totalGlowWeightHuman.toNumber(),
615
706
  totalProtocolFeePayments,
616
- 0.001
707
+ 0.001 // 0.1% tolerance
617
708
  )
618
709
  ) {
619
710
  console.error(
@@ -625,12 +716,15 @@ export async function createWeeklyReport({
625
716
  throw new Error("totalGlowWeight vs protocol fees deviation >0.1% ");
626
717
  }
627
718
 
719
+ // --- Prepare Output Data ---
720
+
721
+ // Key statistics for the report.
628
722
  const headlineStats = {
629
723
  weekNumber: week,
630
- totalCreditsProduced: formatUnits(totalCreditsProduced18dp, 18),
724
+ totalCreditsProduced: formatUnits(totalCreditsProduced18dp, 18), // Original reported total
631
725
  totalCreditsProducedBN: totalCreditsProduced18dp.toString(),
632
- totalGlowWeightInFinalized: totalGlowWeight.toString(),
633
- totalGlowWeightHuman: totalGlowWeightHuman.toString(),
726
+ totalGlowWeightInFinalized: totalGlowWeight.toString(), // Total weight as BigNumber string
727
+ totalGlowWeightHuman: totalGlowWeightHuman.toString(), // Total weight as human-readable decimal
634
728
  totalUSDGWeightInFinalized: totalUSDGWeight.toString(),
635
729
  totalUSDGWeightHuman: totalUSDGWeightHuman.toString(),
636
730
  root: merkleRoot,
@@ -638,6 +732,7 @@ export async function createWeeklyReport({
638
732
  usdgWeightDecimals: USDG_WEIGHT_DECIMAL_PRECISION,
639
733
  };
640
734
 
735
+ // List of shortIds and their final adjusted credit value (human-readable).
641
736
  const shortIdAdjustedList = Array.from(shortIdToAdjustedCredit.entries()).map(
642
737
  ([shortId, creditBigInt]) => ({
643
738
  shortId,
@@ -648,6 +743,7 @@ export async function createWeeklyReport({
648
743
  })
649
744
  );
650
745
 
746
+ // Detailed comparison between originally reported credits and adjusted credits for each farm.
651
747
  const creditsDeviationList = farms.map((farm: any) => {
652
748
  const adj = shortIdToAdjustedCredit.get(String(farm.shortId)) ?? BigInt(0);
653
749
  const adjusted = fromBigInt(adj, USDG_WEIGHT_DECIMAL_PRECISION);
@@ -655,6 +751,7 @@ export async function createWeeklyReport({
655
751
  let deviation: Decimal;
656
752
  let absDeviation: Decimal;
657
753
  let deviationPercent: Decimal;
754
+ // Handle division by zero if produced is zero.
658
755
  if (produced.isZero() && adjusted.isZero()) {
659
756
  deviation = new Decimal(0);
660
757
  absDeviation = new Decimal(0);
@@ -663,7 +760,7 @@ export async function createWeeklyReport({
663
760
  deviation = produced.minus(adjusted);
664
761
  absDeviation = deviation.abs();
665
762
  deviationPercent = deviation
666
- .div(produced.isZero() ? 1 : produced)
763
+ .div(produced.isZero() ? 1 : produced) // Avoid division by zero
667
764
  .mul(100);
668
765
  }
669
766
  return {
@@ -676,13 +773,14 @@ export async function createWeeklyReport({
676
773
  };
677
774
  });
678
775
 
776
+ // Return all calculated data.
679
777
  return {
680
778
  headlineStats,
681
- finalizedLeaves,
682
- leavesWithProofs,
683
- farms,
684
- rawData,
685
- shortIdAdjustedList,
686
- creditsDeviationList,
779
+ finalizedLeaves, // Leaves without proofs (for potential use cases)
780
+ leavesWithProofs, // Leaves with proofs (primary data for distribution)
781
+ farms, // Original filtered farm data
782
+ rawData, // Raw GCA responses
783
+ shortIdAdjustedList, // List of adjusted credits per farm
784
+ creditsDeviationList, // Detailed deviation report per farm
687
785
  };
688
786
  }